{{/* Issues Page Content Tier-based dashboard for SDK repos: each tier answers "what should a maintainer do next". SLA cards track SEP-1730 Tier 1 targets. Non-SDK repos (spec, csharp) fall through to the original volume-stat layout. */}} {{ define "iss-type-badge" }} {{- $colors := dict "bug" "#d73a4a" "enhancement" "#a2eeef" "question" "#d876e3" "documentation" "#0075ca" -}} {{- with . -}} {{ . }} {{- end -}} {{ end }} {{ define "iss-priority-badge" }} {{- $colors := dict "P0" "#b60205" "P1" "#d93f0b" "P2" "#fbca04" "P3" "#c5def5" -}} {{- with . -}} {{ . }} {{- end -}} {{ end }} {{ define "iss-row" }} #{{ .number }} {{ if .is_maintainer }}{{ .author }}{{ else }}{{ .author }}{{ end }} {{ .title }} {{- range .linked_prs }} →#{{ . }}{{ end }} {{ template "iss-type-badge" .type }} {{ template "iss-priority-badge" .priority }} {{ if gt .comment_count 0 }}{{ .comment_count }}{{ else }}{{ end }} {{ if gt .bot_comment_count 0 }}{{ .bot_comment_count }}{{ else }}{{ end }} {{ if .sla_breach }}{{ printf "%.0f" .age_days }}d {{ else if gt .age_days 90.0 }}{{ printf "%.0f" .age_days }}d {{ else }}{{ printf "%.0f" .age_days }}d{{ end }} {{ end }} {{/* Volume/Response/Stale/Labels sections — shared between Stats fold and legacy layout */}} {{ define "iss-volume-sections" }}

Volume

{{ partial "metric-card.html" (dict "label" "Open Issues" "value" .m.issues.open_count "sparkline" .issuesOpenSparkline "sparklineColor" "rgb(0, 102, 204)" "trend" .issuesOpenTrend "trendGoodDirection" "down" "link" .openIssuesLink) }} {{ partial "metric-card.html" (dict "label" "Opened" "value" .m.issues.opened_7d "descriptor" "last 7 days" "link" .opened7dLink) }} {{ partial "metric-card.html" (dict "label" "Opened" "value" .m.issues.opened_30d "descriptor" "last 30 days" "link" .opened30dLink) }} {{ partial "metric-card.html" (dict "label" "Opened" "value" .m.issues.opened_90d "descriptor" "last 90 days" "link" .opened90dLink) }} {{ partial "metric-card.html" (dict "label" "Closed" "value" .m.issues.closed_7d "descriptor" "last 7 days" "link" .closed7dLink) }} {{ partial "metric-card.html" (dict "label" "Closed" "value" .m.issues.closed_30d "descriptor" "last 30 days" "link" .closed30dLink) }} {{ partial "metric-card.html" (dict "label" "Closed" "value" .m.issues.closed_90d "descriptor" "last 90 days" "link" .closed90dLink) }}

Response Time

Time to first maintainer response

{{ partial "metric-card.html" (dict "label" "Average" "value" (partial "format-hours.html" .m.issues.response_time.avg_hours)) }} {{ partial "metric-card.html" (dict "label" "Median" "value" (partial "format-hours.html" .m.issues.response_time.median_hours) "sparkline" .issuesResponseMedianSparkline "sparklineColor" "rgb(108, 117, 125)" "trend" .issuesResponseTrend "trendGoodDirection" "down") }} {{ partial "metric-card.html" (dict "label" "P90" "value" (partial "format-hours.html" .m.issues.response_time.p90_hours)) }} {{ partial "metric-card.html" (dict "label" "P95" "value" (partial "format-hours.html" .m.issues.response_time.p95_hours)) }}

Stale Issues

Issues with no activity

{{ partial "metric-card.html" (dict "label" "Stale" "value" .m.issues.stale_30d "descriptor" ">30 days" "sparkline" .issuesStale30dSparkline "sparklineColor" "rgb(255, 193, 7)" "trend" .issuesStale30dTrend "trendGoodDirection" "down" "link" .stale30dLink) }} {{ partial "metric-card.html" (dict "label" "Stale" "value" .m.issues.stale_60d "descriptor" ">60 days" "link" .stale60dLink) }} {{ partial "metric-card.html" (dict "label" "Stale" "value" .m.issues.stale_90d "descriptor" ">90 days" "link" .stale90dLink) }} {{ partial "metric-card.html" (dict "label" "Reopen Rate" "value" (printf "%.0f%%" (mul .m.issues.reopen_rate 100))) }}
{{ if .m.issues.by_label }}
Issues by Label
{{ $labelSlice := slice }} {{ range $label, $count := .m.issues.by_label }} {{ $labelSlice = $labelSlice | append (dict "label" $label "count" $count) }} {{ end }} {{ range sort $labelSlice "count" "desc" }} {{ $labelLink := printf "%s?q=is:issue+is:open+label:\"%s\"" $.ghBase .label }} {{ end }}
Label Count
{{ .label }} {{ .count }}
{{ end }} {{ end }}{{/* define iss-volume-sections */}} {{/* ─────────────────────────────────────────────────────────────────────── */}} {{ $context := . }} {{ $repoKey := "" }} {{ if reflect.IsMap . }} {{ with .context }}{{ $context = . }}{{ end }} {{ with .repoKey }}{{ $repoKey = . }}{{ end }} {{ end }} {{ $data := partial "load-metrics.html" (dict "context" $context "repoKey" $repoKey) }} {{ $m := $data.metrics }} {{ $t := $data.issuesTiers }} {{ $snapshots := $data.snapshots }} {{ if not $m }}
No data available. Run the aggregation script.
{{ else }} {{ $repoKey := $data.repoKey }} {{ $ghBase := printf "https://github.com/%s/issues" $repoKey }} {{/* Shared sparkline/link vars (used by both tiered UI's Stats fold and the legacy layout) */}} {{ $issuesOpenSparkline := partial "get-sparkline.html" (dict "snapshots" $snapshots "path" "issues.open") }} {{ $issuesResponseMedianSparkline := partial "get-sparkline.html" (dict "snapshots" $snapshots "path" "issues.response_time.median_hours") }} {{ $issuesStale30dSparkline := partial "get-sparkline.html" (dict "snapshots" $snapshots "path" "issues.stale_30d") }} {{ $issuesOpenTrend := partial "calc-trend.html" (dict "sparkline" $issuesOpenSparkline) }} {{ $issuesResponseTrend := partial "calc-trend.html" (dict "sparkline" $issuesResponseMedianSparkline) }} {{ $issuesStale30dTrend := partial "calc-trend.html" (dict "sparkline" $issuesStale30dSparkline) }} {{ $openIssuesLink := printf "%s?q=is:issue+is:open" $ghBase }} {{ $closed7dLink := printf "%s?q=is:issue+is:closed+closed:>%s" $ghBase (now.AddDate 0 0 -7 | time.Format "2006-01-02") }} {{ $closed30dLink := printf "%s?q=is:issue+is:closed+closed:>%s" $ghBase (now.AddDate 0 0 -30 | time.Format "2006-01-02") }} {{ $closed90dLink := printf "%s?q=is:issue+is:closed+closed:>%s" $ghBase (now.AddDate 0 0 -90 | time.Format "2006-01-02") }} {{ $opened7dLink := printf "%s?q=is:issue+created:>%s" $ghBase (now.AddDate 0 0 -7 | time.Format "2006-01-02") }} {{ $opened30dLink := printf "%s?q=is:issue+created:>%s" $ghBase (now.AddDate 0 0 -30 | time.Format "2006-01-02") }} {{ $opened90dLink := printf "%s?q=is:issue+created:>%s" $ghBase (now.AddDate 0 0 -90 | time.Format "2006-01-02") }} {{ $stale30dLink := printf "%s?q=is:issue+is:open+updated:<=%s+sort:updated-asc" $ghBase (now.AddDate 0 0 -30 | time.Format "2006-01-02") }} {{ $stale60dLink := printf "%s?q=is:issue+is:open+updated:<=%s+sort:updated-asc" $ghBase (now.AddDate 0 0 -60 | time.Format "2006-01-02") }} {{ $stale90dLink := printf "%s?q=is:issue+is:open+updated:<=%s+sort:updated-asc" $ghBase (now.AddDate 0 0 -90 | time.Format "2006-01-02") }} {{ $volCtx := dict "m" $m "ghBase" $ghBase "issuesOpenSparkline" $issuesOpenSparkline "issuesOpenTrend" $issuesOpenTrend "issuesResponseMedianSparkline" $issuesResponseMedianSparkline "issuesResponseTrend" $issuesResponseTrend "issuesStale30dSparkline" $issuesStale30dSparkline "issuesStale30dTrend" $issuesStale30dTrend "openIssuesLink" $openIssuesLink "opened7dLink" $opened7dLink "opened30dLink" $opened30dLink "opened90dLink" $opened90dLink "closed7dLink" $closed7dLink "closed30dLink" $closed30dLink "closed90dLink" $closed90dLink "stale30dLink" $stale30dLink "stale60dLink" $stale60dLink "stale90dLink" $stale90dLink }} {{/* ═════════════════════════════════════════════════════════════════════════ TIERED UI — only when issues.json exists (SDK repos). ═════════════════════════════════════════════════════════════════════════ */}} {{ with $t }} {{/* ───────── Row 1: actionable subset by type (4 cards) ───────── */}} {{ with .summary }} {{ $s := . }} {{ $fixClr := cond (gt $s.bugs_fix_ready.p01 0) "text-error" (cond (gt $s.bugs_fix_ready.total 10) "text-warning" "text-success") }} {{ $decClr := cond (gt $s.decisions_pending.p1 0) "text-warning" "" }} {{ $qClr := cond (eq $s.questions_stale_2d 0) "text-success" (cond (lt $s.questions_stale_2d 5) "text-warning" "text-error") }}
{{ partial "metric-card.html" (dict "label" "Bugs ready" "value" $s.bugs_fix_ready.total "valueClass" $fixClr "descriptor" (printf "%d P0/P1 · %d fix proposed" (int $s.bugs_fix_ready.p01) (int ($s.bugs_fix_ready.fix_proposed | default 0))) "info" "bug + ready for work — triaged and reproducible.\nClick to jump to the tier.\n\nRed: any P0/P1\nYellow: > 10\nGreen: ≤ 10") }}
{{ partial "metric-card.html" (dict "label" "Decisions pending" "value" $s.decisions_pending.total "valueClass" $decClr "descriptor" (printf "%d at P1" (int $s.decisions_pending.p1)) "info" "enhancement + needs decision — say yes (→ ready/design) or no (→ close).\nClick to jump to the tier.") }}
{{ partial "metric-card.html" (dict "label" "Questions > 2d" "value" $s.questions_stale_2d "valueClass" $qClr "info" "Questions past 2 business days with no maintainer response.\nClick to jump to the tier.\n\nGreen: 0\nYellow: 1–4\nRed: 5+") }}
{{ partial "metric-card.html" (dict "label" "Close candidates" "value" $s.close_candidates.total "descriptor" (printf "median %dd old" (int $s.close_candidates.median_age)) "info" "potentially close + repro/confirm requests expired (>14d). Across all types.") }}
{{/* ───────── Row 2: SLA breaches (4 cards) ───────── */}} {{ $p0Clr := cond (gt $s.sla.p0_7d_breach 0) "text-error" (cond (gt $s.p0_open 0) "text-warning" "text-success") }} {{ $p1Clr := cond (eq $s.sla.p1_90d_breach 0) "text-success" (cond (lt $s.sla.p1_90d_breach 5) "text-warning" "text-error") }} {{ $reproClr := cond (eq $s.needs_repro_14d 0) "text-success" (cond (lt $s.needs_repro_14d 5) "text-warning" "text-error") }} {{ $botClr := cond (eq $s.untriaged_count 0) "text-success" (cond (lt $s.untriaged_count 3) "text-warning" "text-error") }}
{{ partial "metric-card.html" (dict "label" "P0 open" "value" $s.p0_open "valueClass" $p0Clr "descriptor" (printf "%d past 7d SLA" (int $s.sla.p0_7d_breach)) "info" "All open P0 issues. SEP-1730: resolve within 7 days.\n\nGreen: 0\nYellow: any open\nRed: any past 7d") }}
{{ partial "metric-card.html" (dict "label" "P1 > 90d" "value" $s.sla.p1_90d_breach "valueClass" $p1Clr "info" "P1 issues open longer than 90 days.\nNot in SEP-1730 — surfaces aspirational-P1 rot.\n\nGreen: 0\nYellow: 1–4\nRed: 5+") }}
{{ partial "metric-card.html" (dict "label" "Repro expired" "value" $s.needs_repro_14d "valueClass" $reproClr "info" "needs repro / needs confirmation requested >14d ago, no reporter reply. Auto-close candidates.\n\nGreen: 0\nYellow: 1–4\nRed: 5+") }}
{{ partial "metric-card.html" (dict "label" "Bot pending" "value" $s.untriaged_count "valueClass" $botClr "info" "No type label yet — bot hasn't run, or needs manual triage.\nShould be ~0 within 30min of any issue activity.\n\nGreen: 0\nYellow: 1–2\nRed: 3+") }}
{{ end }}{{/* with .summary */}} {{/* ───────── Stats fold ───────── */}}
Stats — volume, response time, staleness, labels
{{ template "iss-volume-sections" $volCtx }}
{{/* ───────── Filter + tier sections ───────── */}}
{{ range .groups }} {{ $groupCount := 0 }}{{ range .tiers }}{{ $groupCount = add $groupCount (len .issues) }}{{ end }}

{{ .name }} ({{ $groupCount }})

{{ .blurb }}

{{ range .tiers }}
{{ .name }} ({{ len .issues }}){{ .blurb }} {{ range .issues }}{{ template "iss-row" . }}{{ end }}
# Author Title Labels 💬 🤖 Age
{{ end }}{{/* range .tiers */}}
{{ end }}{{/* range .groups */}} {{ else }}{{/* with $t — no tier data, show legacy layout (spec/csharp/not-yet-computed) */}} {{ template "iss-volume-sections" $volCtx }} {{ if $m.issues.issues_without_maintainer_response }}

Issues Awaiting Maintainer Response

Sorted by longest wait time first

{{ range $m.issues.issues_without_maintainer_response }} {{ end }}
Issue Title Labels Comments Waiting
#{{ .number }} {{ .title }} {{ $labels := .labels }}{{ $labelCount := len $labels }} {{ if eq $labelCount 0 }}(unlabeled) {{ else }}{{ range first 2 $labels }}{{ . }}{{ end }}{{ if gt $labelCount 2 }}+{{ sub $labelCount 2 }}{{ end }}{{ end }} {{ if gt .commentCount 0 }}{{ .commentCount }}{{ else }}0{{ end }} {{ if gt .daysWaiting 30 }}{{ .daysWaiting }}d {{ else if gt .daysWaiting 7 }}{{ .daysWaiting }}d {{ else }}{{ .daysWaiting }}d{{ end }}
{{ end }} {{ end }}{{/* with $t */}} {{ end }}{{/* if $m */}}