diff --git a/apps/decodex/src/orchestrator/operator_dashboard.html b/apps/decodex/src/orchestrator/operator_dashboard.html index 920071e6..3e06191f 100644 --- a/apps/decodex/src/orchestrator/operator_dashboard.html +++ b/apps/decodex/src/orchestrator/operator_dashboard.html @@ -3575,11 +3575,7 @@

Run History

} function compactStateToken(value) { - if (!value) { - return "none"; - } - - return String(value).trim().toLowerCase().replace(/_/g, " "); + return formatDetailToken(value); } function formatTimestamp(value) { @@ -4229,7 +4225,7 @@

Run History

function formatDetailToken(value) { const token = String(value || "").trim(); - return token ? token.toUpperCase() : "NONE"; + return token || "NONE"; } function formatPriority(priority) { @@ -4530,6 +4526,9 @@

Run History

function titleCaseLabel(label) { return String(label || "").replace(/\b[A-Za-z][A-Za-z0-9]*\b/g, (word) => { + if (/^[A-Z0-9]+$/.test(word) && /[A-Z]/.test(word)) { + return word; + } const lower = word.toLowerCase(); const acronym = FIELD_LABEL_ACRONYMS.get(lower); return acronym || `${lower.charAt(0).toUpperCase()}${lower.slice(1)}`; @@ -4599,6 +4598,22 @@

Run History

return renderField(label, value, valueClass, titleCaseLabel, "card-field"); } + function cardFactValueClass(value, explicitClass = "") { + return [explicitClass, String(value || "").trim() === "NONE" ? "is-muted" : ""] + .filter(Boolean) + .join(" "); + } + + function optionalCardToken(value) { + const token = String(value || "").trim(); + return token || "NONE"; + } + + function reviewThreadToken(count) { + const numericCount = Number(count); + return Number.isFinite(numericCount) && numericCount > 0 ? String(numericCount) : "NONE"; + } + function renderAttentionFacts(candidate) { const attention = candidate.attention; if (!attention) { @@ -7274,9 +7289,9 @@

Run History

["Run", activeRun.run_id], ["Operation", humanizeToken(activeRun.current_operation || activeRun.phase)], ["Checks", compactStateToken(lane.check_state)], - ["Threads", lane.unresolved_review_threads == null ? "none" : String(lane.unresolved_review_threads)], - ["PR", lane.pr_url || "none"], - ["Branch", lane.branch_name], + ["Threads", reviewThreadToken(lane.unresolved_review_threads)], + ["PR", optionalCardToken(lane.pr_url)], + ["Branch", optionalCardToken(lane.branch_name)], ], }); continue; @@ -7293,9 +7308,9 @@

Run History

status: postReviewBlockerStatus(lane, blockerScope), facts: [ ["Checks", compactStateToken(lane.check_state)], - ["Threads", lane.unresolved_review_threads == null ? "none" : String(lane.unresolved_review_threads)], - ["PR", lane.pr_url || "none"], - ["Branch", lane.branch_name], + ["Threads", reviewThreadToken(lane.unresolved_review_threads)], + ["PR", optionalCardToken(lane.pr_url)], + ["Branch", optionalCardToken(lane.branch_name)], ], }); continue; @@ -7311,9 +7326,9 @@

Run History

status: lane.check_state ? `checks ${compactStateToken(lane.check_state)}` : "waiting", facts: [ ["Review decision", compactStateToken(lane.review_decision)], - ["Threads", lane.unresolved_review_threads == null ? "none" : String(lane.unresolved_review_threads)], - ["PR", lane.pr_url || "none"], - ["Branch", lane.branch_name], + ["Threads", reviewThreadToken(lane.unresolved_review_threads)], + ["PR", optionalCardToken(lane.pr_url)], + ["Branch", optionalCardToken(lane.branch_name)], ], }); continue; @@ -7330,8 +7345,9 @@

Run History

facts: [ ["Review decision", compactStateToken(lane.review_decision)], ["Checks", compactStateToken(lane.check_state)], - ["PR", lane.pr_url || "none"], - ["Branch", lane.branch_name], + ["Threads", reviewThreadToken(lane.unresolved_review_threads)], + ["PR", optionalCardToken(lane.pr_url)], + ["Branch", optionalCardToken(lane.branch_name)], ], }); } @@ -8021,7 +8037,7 @@

${escapeHtml(item.title)}

${statusLabel(item.status, item.tone)}
- ${item.facts.map(([label, value]) => cardField(label, value)).join("")} + ${item.facts.map(([label, value, valueClass]) => cardField(label, value, cardFactValueClass(value, valueClass))).join("")}
`, diff --git a/apps/decodex/src/orchestrator/tests/operator/status/dashboard.rs b/apps/decodex/src/orchestrator/tests/operator/status/dashboard.rs index f806d453..ab9e9e23 100644 --- a/apps/decodex/src/orchestrator/tests/operator/status/dashboard.rs +++ b/apps/decodex/src/orchestrator/tests/operator/status/dashboard.rs @@ -944,7 +944,8 @@ fn operator_dashboard_projects_keep_status_summary_compact() { assert!(response.contains("Appears after /state publishes a snapshot.")); assert!(response.contains("renderQueuedCandidates(")); assert!(response.contains("function formatDetailToken(value)")); - assert!(response.contains("return token ? token.toUpperCase() : \"NONE\";")); + assert!(response.contains("return token || \"NONE\";")); + assert!(!response.contains("return token ? token.toUpperCase() : \"NONE\";")); assert!(response.contains("return priority == null ? \"NONE\" : `P${priority}`;")); assert!(response.contains("function queuedCandidateSummaryIsNoise(summary)")); assert!(response.contains("normalized.includes(\"systemerror\")")); @@ -970,7 +971,9 @@ fn operator_dashboard_projects_keep_status_summary_compact() { assert!(!response.contains("metadata ")); assert!(!response.contains("telemetry ")); assert!(response.contains("renderActionCards(")); - assert!(response.contains("${item.facts.map(([label, value]) => cardField(label, value)).join(\"\")}")); + assert!(response.contains("function cardFactValueClass(value, explicitClass = \"\")")); + assert!(response.contains("String(value || \"\").trim() === \"NONE\" ? \"is-muted\" : \"\"")); + assert!(response.contains("${item.facts.map(([label, value, valueClass]) => cardField(label, value, cardFactValueClass(value, valueClass))).join(\"\")}")); assert!(!response.contains("${item.facts.map(([label, value]) => field(label, value)).join(\"\")}")); assert!(!response.contains("No running lanes")); assert!(!response.contains("No queued issues")); @@ -1091,7 +1094,16 @@ fn operator_dashboard_normalizes_review_state_tokens() { let response = dashboard_response(); assert!(response.contains("function compactStateToken(value)")); - assert!(response.contains("return String(value).trim().toLowerCase().replace(/_/g, \" \");")); + assert!(response.contains("return formatDetailToken(value);")); + assert!(response.contains("function reviewThreadToken(count)")); + assert!( + response.contains( + "return Number.isFinite(numericCount) && numericCount > 0 ? String(numericCount) : \"NONE\";", + ) + ); + assert!(response.contains("function optionalCardToken(value)")); + assert!(response.contains("return token || \"NONE\";")); + assert!(response.contains("if (/^[A-Z0-9]+$/.test(word) && /[A-Z]/.test(word))")); assert!(response.contains( "status: lane.mergeable ? `merge ${compactStateToken(lane.mergeable)}` : \"ready\"," )); @@ -1100,10 +1112,14 @@ fn operator_dashboard_normalizes_review_state_tokens() { )); assert!(response.contains("`review ${compactStateToken(lane.review_decision)}`")); assert!(response.contains("[\"Checks\", compactStateToken(lane.check_state)]")); + assert!(response.contains("[\"Threads\", reviewThreadToken(lane.unresolved_review_threads)]")); assert!(response.contains("[\"Review decision\", compactStateToken(lane.review_decision)]")); + assert!(response.contains("[\"PR\", optionalCardToken(lane.pr_url)]")); assert!(!response.contains("`merge ${humanizeToken(lane.mergeable)}`")); assert!(!response.contains("`checks ${humanizeToken(lane.check_state)}`")); assert!(!response.contains("[\"Checks\", lane.check_state || \"none\"]")); + assert!(!response.contains("lane.unresolved_review_threads == null ? \"none\"")); + assert!(!response.contains("lane.pr_url || \"none\"")); } #[test]