Skip to content

Log viewer component

components specs/components/log-viewer.kmd

The streaming build/run log surface for Koder Pipe (CI), Hub, and any product that shows machine output: monospace append-only stream with ANSI color, collapsible step groups, search, follow-tail autoscroll, virtualization for huge logs, plus a companion job/workflow DAG graph for multi-step builds. Modeled after the GitHub Actions log + workflow graph (Primer).

When this spec applies

Primary triggers

All triggers

Specification body

Component — Log viewer

Status: v0.1.0 — Draft. Promoted from the GitHub Primer parity scan (meta/docs/stack #092). Live URL once rendered: kds.koder.dev/<locale>/components/components-log-viewer.html.

R1 — Log stream

  • Monospace, append-only; new lines stream in at the tail.
  • Renders ANSI SGR color/style (the common CI subset: 8/16/256/truecolor foreground+background, bold, underline) mapped onto Verge terminal tokens (specs/themes/verge.kmd) — never raw ANSI palette hex, so light/dark stay legible.
  • Per-line: a line number gutter and an optional timestamp column (toggle).
  • Lines wrap or scroll-horizontally per a user toggle; default no-wrap.

R2 — Step groups

  • Output is grouped into collapsible steps (a CI step / phase). A group header shows its name, duration, and a specs/components/state-label.kmd- style status (queued / running / success / failed / skipped).
  • Failed groups auto-expand; successful ones default collapsed.
  • Deep-linking to a line expands its group and scrolls to it.

R3 — Follow tail (autoscroll)

  • While running, the viewer follows the tail (autoscrolls to newest).
  • Scrolling up pauses follow and shows a "Jump to bottom / Resume" control; reaching the bottom resumes follow.
  • Follow never fights the user (no scroll yank while they read history).

R4 — Search & navigation

  • In-log search highlights matches with next/prev navigation and a match count; search spans collapsed groups (expanding on match).
  • Raw view + download (the unstyled text) is always available.

R5 — Scale

  • Virtualize rendering for large logs (only on-screen lines in the DOM); the line count and any server-side truncation/rotation are disclosed (no silent cap).
  • Streaming backpressure: coalesce bursts so the UI stays responsive.

R6 — Workflow / job graph (multi-step builds)

  • A companion graph visualizes the pipeline DAG: nodes = jobs, edges = dependencies (needs), each node colored by the same status set as R2.
  • Selecting a node focuses that job's log stream.
  • The graph augments — it is never the only way to read status; the grouped log + status labels carry it textually (R7).

R7 — Accessibility & i18n

  • Status conveyed by label text + icon, not color alone (WCAG 1.4.1) — reusing specs/components/state-label.kmd semantics.
  • New-line streaming is NOT a raw live region (would flood AT); instead step-completion + failures announce via a polite, throttled live region.
  • Skeletons (specs/components/skeleton.kmd) cover initial load.
  • Chrome strings (step states, "Jump to bottom", "Download", durations) localize per specs/i18n/contract.kmd; log content itself is never translated.

Não-escopo

  • ANSI cursor-control / TUI repainting (logs are append-only; full PTY emulation is the terminal's domain, kterm).
  • Log storage / retention / search backend (Koder Pipe / observe).
  • Metrics charts (separate dashboards spec).

Requirements (testable)

Requirement: Streaming log rendering {#req-log-viewer-stream}

The log viewer SHALL render output as a monospace, append-only stream that appends new lines at the tail, exposes a line-number gutter, and maps ANSI SGR sequences (foreground/background color, bold, underline) onto Verge terminal tokens rather than raw ANSI palette hex.

Scenario: New line appended at the tail

  • GIVEN a log viewer showing an in-progress stream with N rendered lines
  • WHEN the backend emits a new log line
  • THEN the new line is appended after line N as line N+1 in the DOM
  • AND the line-number gutter shows the incremented number for the new line

Scenario: ANSI color mapped to Verge tokens

  • GIVEN a log line containing an ANSI SGR red-foreground escape sequence
  • WHEN the line is rendered
  • THEN the visible text carries a Verge terminal color token class, not a raw ANSI palette hex value
  • AND no literal ANSI escape characters appear in the rendered text

Requirement: Collapsible step groups {#req-log-viewer-step-groups}

The log viewer SHALL group output into collapsible steps whose header shows name, duration, and a state-label status, and it SHALL auto-expand failed groups while collapsing successful ones by default.

Scenario: Failed step auto-expands, successful step collapses

  • GIVEN a completed run with one step in status "failed" and one in status "success"
  • WHEN the log viewer renders the run
  • THEN the failed step group is expanded showing its output lines
  • AND the successful step group is collapsed by default
  • AND each group header displays its name, duration, and a state-label status
  • GIVEN a deep link that references a line inside a collapsed step group
  • WHEN the viewer opens that deep link
  • THEN the enclosing step group expands
  • AND the viewport scrolls to the referenced line

Requirement: Follow-tail autoscroll {#req-log-viewer-follow-tail}

While a run is streaming the log viewer SHALL follow the tail by autoscrolling to the newest line, and it SHALL pause following when the user scrolls up without yanking the scroll position back down while they read history.

Scenario: Autoscroll keeps newest line in view while following

  • GIVEN a running log with follow-tail active
  • WHEN a new line is appended at the tail
  • THEN the viewport scrolls so the newest line is visible

Scenario: Scrolling up pauses follow and offers resume

  • GIVEN a running log with follow-tail active
  • WHEN the user scrolls up away from the bottom
  • THEN follow-tail is paused and the viewport stays at the user's scroll position when new lines arrive
  • AND a "Jump to bottom / Resume" control is shown

The log viewer SHALL provide in-log search that highlights matches with next/previous navigation and a match count spanning collapsed groups, and it SHALL always offer a raw unstyled text view with download.

Scenario: Search highlights matches and expands collapsed hits

  • GIVEN a log with a matching term located inside a collapsed step group
  • WHEN the user searches for that term
  • THEN the match count reflects the occurrence inside the collapsed group
  • AND navigating to that match expands the group and highlights the matched text

Scenario: Raw view and download available

  • GIVEN any log viewer instance
  • WHEN the user opens the raw view
  • THEN the unstyled log text is shown without ANSI styling
  • AND a download control for the raw text is available

Requirement: Accessibility and i18n {#req-log-viewer-a11y}

The log viewer SHALL convey step status by label text plus icon rather than color alone (WCAG 1.4.1), SHALL NOT expose per-line streaming as a raw live region, and SHALL announce step-completion and failures through a polite, throttled live region while localizing chrome strings but never the log content.

Scenario: Status not conveyed by color alone

  • GIVEN a step group in status "failed"
  • WHEN the group header is rendered
  • THEN the failure is conveyed by visible label text and an icon, not by color alone

Scenario: Streaming lines do not flood assistive tech

  • GIVEN a running log streaming many new lines per second
  • WHEN individual log lines are appended
  • THEN the per-line container is not a live region and does not announce each line to assistive technology
  • BUT a step-completion or failure event announces once via a polite, throttled live region

Scenario: Chrome localizes, log content does not

  • GIVEN the viewer rendered under a non-en-US locale
  • WHEN chrome strings such as "Jump to bottom" and "Download" are displayed
  • THEN those chrome strings are localized per the i18n contract
  • AND the streamed log content text itself remains untranslated

References