From 9409c61b5fb5c319da79e75a751f35878b5194b5 Mon Sep 17 00:00:00 2001 From: root Date: Sun, 26 Jul 2026 10:07:50 -0500 Subject: [PATCH] fix: deduplicate backlog queue items --- desloppify/engine/_work_queue/snapshot.py | 44 ++++++++++--------- .../test_work_queue_plan_order_and_triage.py | 5 ++- 2 files changed, 27 insertions(+), 22 deletions(-) diff --git a/desloppify/engine/_work_queue/snapshot.py b/desloppify/engine/_work_queue/snapshot.py index 04984cded..b1a5ea054 100644 --- a/desloppify/engine/_work_queue/snapshot.py +++ b/desloppify/engine/_work_queue/snapshot.py @@ -14,10 +14,6 @@ WORKFLOW_DEFERRED_DISPOSITION_ID, WORKFLOW_RUN_SCAN_ID, ) -from desloppify.engine._plan.schema import ( - executable_objective_ids as _executable_objective_ids, - live_planned_queue_ids as _live_planned_queue_ids, -) from desloppify.engine._plan.refresh_lifecycle import ( LIFECYCLE_PHASE_ASSESSMENT_POSTFLIGHT, LIFECYCLE_PHASE_EXECUTE, @@ -29,12 +25,17 @@ current_lifecycle_phase, derive_display_phase, ) +from desloppify.engine._plan.schema import ( + executable_objective_ids as _executable_objective_ids, +) +from desloppify.engine._plan.schema import ( + live_planned_queue_ids as _live_planned_queue_ids, +) from desloppify.engine._plan.triage.snapshot import build_triage_snapshot from desloppify.engine._state.filtering import path_scoped_issues from desloppify.engine._state.issue_semantics import ( counts_toward_objective_backlog, is_assessment_request, - is_review_work_item, is_triage_finding, ) from desloppify.engine._state.schema import StateModel @@ -505,21 +506,24 @@ def _build_backlog( p: _Partitions, execution_ids: set[str], ) -> list[WorkQueueItem]: - return [ - item - for item in ( - [ - *p.objective_items, - *p.initial_review_items, - *p.postflight_assessment_items, - *p.review_issue_items, - *p.scan_items, - *p.postflight_workflow_items, - *p.triage_items, - ] - ) - if item.get("id", "") not in execution_ids - ] + backlog: list[WorkQueueItem] = [] + seen_ids = set(execution_ids) + for item in ( + *p.objective_items, + *p.initial_review_items, + *p.postflight_assessment_items, + *p.review_issue_items, + *p.scan_items, + *p.postflight_workflow_items, + *p.triage_items, + ): + item_id = item.get("id", "") + if item_id and item_id in seen_ids: + continue + if item_id: + seen_ids.add(item_id) + backlog.append(item) + return backlog # --------------------------------------------------------------------------- diff --git a/desloppify/tests/review/test_work_queue_plan_order_and_triage.py b/desloppify/tests/review/test_work_queue_plan_order_and_triage.py index 2ae406068..26b77cdc9 100644 --- a/desloppify/tests/review/test_work_queue_plan_order_and_triage.py +++ b/desloppify/tests/review/test_work_queue_plan_order_and_triage.py @@ -3,12 +3,12 @@ from __future__ import annotations from desloppify.engine._plan.refresh_lifecycle import carry_forward_subjective_review +from desloppify.engine._work_queue.core import QueueBuildOptions +from desloppify.engine._work_queue.core import build_work_queue as _build_work_queue from desloppify.engine.planning.queue_policy import ( build_backlog_queue, build_execution_queue, ) -from desloppify.engine._work_queue.core import QueueBuildOptions -from desloppify.engine._work_queue.core import build_work_queue as _build_work_queue def build_work_queue(state, **kwargs): @@ -527,6 +527,7 @@ def test_backlog_queue_excludes_execution_objective_items(): ids = [item["id"] for item in queue["items"]] assert "smells::src/a.py::planned" not in ids assert "smells::src/b.py::unplanned" in ids + assert ids.count("smells::src/b.py::unplanned") == 1 assert "workflow::run-scan" not in ids