From 0bed9a35f0362fa139c9a07a775f324bc9045b47 Mon Sep 17 00:00:00 2001 From: Chris Scott <99081550+chriswritescode-dev@users.noreply.github.com> Date: Fri, 5 Jun 2026 09:51:06 -0400 Subject: [PATCH 1/3] feat: add loop detail navigation with hash routing to forge dashboard --- src/dashboard/render.ts | 396 ++++++++++++++++++++++------------ test/dashboard/render.test.ts | 60 ++++++ 2 files changed, 315 insertions(+), 141 deletions(-) diff --git a/src/dashboard/render.ts b/src/dashboard/render.ts index 64cafb61d..330844ba1 100644 --- a/src/dashboard/render.ts +++ b/src/dashboard/render.ts @@ -57,11 +57,6 @@ export function renderDashboardHtml(): string { border: 1px solid #30363d; border-radius: 6px; margin-bottom: 8px; background: #0d1117; overflow: hidden; } - .loop-header { - display: flex; align-items: center; gap: 10px; padding: 8px 12px; - cursor: pointer; user-select: none; - } - .loop-header:hover { background: #161b22; } .status-badge { display: inline-block; padding: 2px 8px; border-radius: 10px; font-size: 0.75rem; font-weight: 600; text-transform: uppercase; @@ -73,7 +68,6 @@ export function renderDashboardHtml(): string { .status-stalled { background: #d29922; color: #fff; } .loop-info { font-size: 0.85rem; color: #8b949e; flex: 1; } .loop-info strong { color: #c9d1d9; } - .expand-icon { color: #484f58; font-size: 0.8rem; width: 16px; text-align: center; } .loop-detail { padding: 8px 12px 12px; border-top: 1px solid #30363d; font-size: 0.85rem; } .loop-detail h4 { color: #f0f6fc; margin: 8px 0 4px; font-size: 0.95rem; } .loop-detail h4:first-child { margin-top: 0; } @@ -91,6 +85,25 @@ export function renderDashboardHtml(): string { .timestamp { font-size: 0.75rem; color: #484f58; margin-bottom: 12px; } .error-text { color: #f85149; } .dim { color: #484f58; } + .resizable-block { + resize: both; overflow: auto; + min-height: 120px; height: 60vh; max-height: none; + border: 1px solid #30363d; border-radius: 4px; + background: #0d1117; padding: 8px; margin-top: 4px; + } + pre.resizable-block { white-space: pre-wrap; word-break: break-word; font-size: 0.78rem; color: #8b949e; } + .loop-row { + display: flex; align-items: center; gap: 10px; padding: 8px 12px; + cursor: pointer; user-select: none; border: 1px solid #30363d; + border-radius: 6px; margin-bottom: 8px; background: #0d1117; + } + .loop-row:hover { background: #161b22; } + .back-to-loops { + display: inline-flex; align-items: center; gap: 6px; cursor: pointer; + color: #58a6ff; font-size: 0.85rem; margin-bottom: 12px; user-select: none; + } + .back-to-loops:hover { color: #79c0ff; } + .loop-detail-header { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; } @@ -101,11 +114,11 @@ export function renderDashboardHtml(): string {
@@ -411,12 +455,19 @@ export function renderDashboardHtml(): string { var detail = document.createElement('div'); detail.className = 'loop-detail'; - // Completion summary (resizable) + // Completion summary (markdown) if (lp.completionSummary) { + var csLabel = document.createElement('h4'); + csLabel.className = 'section-label'; + csLabel.textContent = 'Completion Summary'; + detail.appendChild(csLabel); + var csWrap = document.createElement('div'); + csWrap.className = 'markdown-scrollable'; var cs = document.createElement('div'); - cs.className = 'resizable-block'; - cs.textContent = lp.completionSummary; - detail.appendChild(cs); + cs.className = 'markdown-content'; + cs.innerHTML = marked.parse(lp.completionSummary); + csWrap.appendChild(cs); + detail.appendChild(csWrap); } // Sections @@ -517,26 +568,34 @@ export function renderDashboardHtml(): string { } } - // Last audit result (resizable pre) + // Last audit result (markdown) if (dashLoop.lastAuditResult) { var laTitle = document.createElement('h4'); + laTitle.className = 'section-label'; laTitle.textContent = 'Last Audit Result'; detail.appendChild(laTitle); - var laPre = document.createElement('pre'); - laPre.className = 'resizable-block'; - laPre.textContent = dashLoop.lastAuditResult; - detail.appendChild(laPre); + var laWrap = document.createElement('div'); + laWrap.className = 'markdown-scrollable'; + var laDiv = document.createElement('div'); + laDiv.className = 'markdown-content'; + laDiv.innerHTML = marked.parse(dashLoop.lastAuditResult); + laWrap.appendChild(laDiv); + detail.appendChild(laWrap); } - // Plan (resizable pre) + // Plan (markdown) if (dashLoop.plan) { var planTitle = document.createElement('h4'); + planTitle.className = 'section-label'; planTitle.textContent = 'Plan'; detail.appendChild(planTitle); - var planPre = document.createElement('pre'); - planPre.className = 'resizable-block'; - planPre.textContent = dashLoop.plan; - detail.appendChild(planPre); + var planWrap = document.createElement('div'); + planWrap.className = 'markdown-scrollable'; + var planDiv = document.createElement('div'); + planDiv.className = 'markdown-content'; + planDiv.innerHTML = marked.parse(dashLoop.plan); + planWrap.appendChild(planDiv); + detail.appendChild(planWrap); } loopEl.appendChild(detail); diff --git a/src/version.ts b/src/version.ts index 53c9225f6..acb50bf14 100644 --- a/src/version.ts +++ b/src/version.ts @@ -1 +1 @@ -export const VERSION = '0.4.15' +export const VERSION = '0.4.16'