From 31d9fe56c55db7c4083beea3f6c0d5c68edbbcf7 Mon Sep 17 00:00:00 2001 From: Yvette Carlisle Date: Wed, 13 May 2026 18:48:22 +0800 Subject: [PATCH] {"schema":"decodex/commit/1","summary":"Fix operator claimed lane visibility","authority":"manual"} --- .../src/orchestrator/operator_dashboard.html | 16 ++++++++++++---- .../tests/operator/status/dashboard.rs | 13 ++++++++++++- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/apps/decodex/src/orchestrator/operator_dashboard.html b/apps/decodex/src/orchestrator/operator_dashboard.html index 6f3c3b9f..3169f1c7 100644 --- a/apps/decodex/src/orchestrator/operator_dashboard.html +++ b/apps/decodex/src/orchestrator/operator_dashboard.html @@ -7490,12 +7490,21 @@

Run History

const historyRuns = sessionHistoryRuns(snapshot); const postReviewLanes = snapshot?.post_review_lanes ?? []; const postReviewIssueKeys = new Set(postReviewLanes.flatMap(issueIdentityKeys)); - const activeRunByIssue = new Map(activeRuns.map((run) => [run.issue_id, run])); + const activeRunByIssue = new Map(); + for (const run of activeRuns) { + for (const key of issueIdentityKeys(run)) { + if (!activeRunByIssue.has(key)) { + activeRunByIssue.set(key, run); + } + } + } const queuedCandidates = [...(snapshot?.queued_candidates ?? [])] .map((candidate) => { - const activeRun = activeRunByIssue.get(candidate.issue_id); + const activeRun = issueIdentityKeys(candidate) + .map((key) => activeRunByIssue.get(key)) + .find(Boolean); - if (activeRun && candidate.classification === "claimed") { + if (activeRun) { return { ...candidate, display_classification: "owned_active", @@ -7509,7 +7518,6 @@

Run History

const queueBacklogCandidates = queuedCandidates.filter( (candidate) => candidate.display_classification !== "owned_active" && - candidate.classification !== "claimed" && candidate.classification !== "closed" && !issueMatchesKeySet(candidate, postReviewIssueKeys), ); diff --git a/apps/decodex/src/orchestrator/tests/operator/status/dashboard.rs b/apps/decodex/src/orchestrator/tests/operator/status/dashboard.rs index de943011..295e0c8e 100644 --- a/apps/decodex/src/orchestrator/tests/operator/status/dashboard.rs +++ b/apps/decodex/src/orchestrator/tests/operator/status/dashboard.rs @@ -1319,7 +1319,6 @@ fn operator_dashboard_flow_counts_distinguish_intake_attention() { assert!(response.contains("intakeAttentionCount")); assert!(response.contains("queuedBlockedWithoutAttention")); assert!(response.contains("attention.thread_status && attention.thread_status !== \"systemError\"")); - assert!(response.contains("candidate.classification !== \"claimed\"")); assert!(response.contains("queueBacklogCandidates.filter(queuedCandidateNeedsAttention).length")); assert!(response.contains( "${pluralize(derived.postReviewLanes.length, \"PR\")} ยท ${pluralize(derived.reviewBlockerCount, \"needs attention\", \"need attention\")}" @@ -1335,6 +1334,18 @@ fn operator_dashboard_flow_counts_distinguish_intake_attention() { assert!(!response.contains("const repairCount = attentionItems.length;")); } +#[test] +fn operator_dashboard_does_not_hide_claimed_queue_without_local_lane() { + let response = dashboard_response(); + + assert!(response.contains("const activeRunByIssue = new Map();")); + assert!(response.contains("for (const key of issueIdentityKeys(run))")); + assert!(response.contains("const activeRun = issueIdentityKeys(candidate)")); + assert!(response.contains("if (activeRun) {")); + assert!(!response.contains("activeRun && candidate.classification === \"claimed\"")); + assert!(!response.contains("candidate.classification !== \"claimed\" &&")); +} + #[test] fn operator_dashboard_prioritizes_needs_attention_reason_over_retry_count() { let response = dashboard_response();