Skip to content

feat(0.2): empty-state helpers + visual regression goldens (Tracks 10.6/10.8)#149

Open
pmclSF wants to merge 1 commit intomainfrom
feat/0.2-track10-visual-finishing
Open

feat(0.2): empty-state helpers + visual regression goldens (Tracks 10.6/10.8)#149
pmclSF wants to merge 1 commit intomainfrom
feat/0.2-track10-visual-finishing

Conversation

@pmclSF
Copy link
Copy Markdown
Owner

@pmclSF pmclSF commented May 2, 2026

Summary

Two Track 10 deliverables that lift the visual / UX side of 0.2.0
from "every renderer invents its own empty-state message" to "one
designed vocabulary, regression-locked."

  • Track 10.6 — Empty state helpers. Seven designed kinds
    (zero-findings, no-AI-surfaces, no-policy, first-run,
    no-impact, no-test-selection, no-migration-candidates) with
    terminal-text + markdown render targets, voice & tone rules
    locked at the test level.
  • Track 10.8 — Visual regression goldens (foundation). Seven
    byte-for-byte golden files + drift gate that verifies the
    goldens directory tracks the shipped enum 1:1. Pattern extends
    to PR-comment markdown / SARIF / HTML when those land.

What changed

New code:

  • internal/reporting/empty_states.go — EmptyStateKind enum,
    EmptyStateFor / RenderEmptyState / EmptyStateMarkdown helpers
  • internal/reporting/insights_report_v2.go — first integration:
    swaps the bare "No significant issues detected." line for the
    designed EmptyZeroFindings rendering

New tests (11):

  • contract: all shipped kinds have a designed header
  • voice & tone: no exclamation, no emoji, no British spellings
  • next-move: every kind references a command in backticks
  • markdown render: blockquote callout shape
  • terminal render: header + indented arrow next-move
  • goldens: 7 byte-for-byte assertions
  • drift gate: goldens dir matches shipped enum 1:1

New goldens:

  • testdata/empty_state_goldens/{zero_findings,no_ai_surfaces, no_policy_file,first_run,no_impact,no_test_selection, no_migration_candidates}.txt — one per kind

Why these two together

10.6 (helpers) and 10.8 (goldens) form a single coherent unit:
the helpers define the vocabulary, the goldens lock it. Shipping
just the helpers without the goldens leaves the visual contract
unenforced; shipping just the goldens without designed messages
makes them low-leverage. Together they give the broader Track 10
visual identity work a stable foundation to build on.

Test plan

  • go build ./... clean
  • go test ./internal/reporting/... — 11 new tests pass +
    existing tests unaffected
  • go test ./... — full suite green, no regression
  • make docs-verify passes
  • Manual smoke: terrain insights on a clean repo renders
    the new "Nothing to flag" header with next-move (separate
    verification — needs a clean fixture)

Plan tracker

Closes Track 10.6 + 10.8. Track 10 remaining: 10.2 renderer audit

🤖 Generated with Claude Code

….6/10.8)

Two Track 10 deliverables that lift the visual / UX side of 0.2.0
from "every renderer invents its own empty-state message" to "one
designed vocabulary, regression-locked."

Track 10.6 — Empty state helpers
  New `internal/reporting/empty_states.go` defines an EmptyStateKind
  enum with seven shipped kinds (zero-findings, no-AI-surfaces,
  no-policy, first-run, no-impact, no-test-selection,
  no-migration-candidates) plus three render targets:
    - EmptyStateFor(kind) → structured EmptyState (Header + NextMove)
    - RenderEmptyState(io.Writer, kind) → terminal-text rendering
    - EmptyStateMarkdown(kind) → blockquote-callout markdown

  Each shipped kind carries a designed header and a next-move nudge
  that names a concrete `terrain ...` command the user can run.
  Three contract tests enforce the design rules:
    - every kind has a non-empty designed header
    - voice & tone — no exclamation marks, no emoji codepoints, no
      British spellings (Track 10.7 voice rules locked at the test
      level)
    - every shipped kind's next-move references a command in
      backticks (no purely invitational empty states)

  First integration: `internal/reporting/insights_report_v2.go`
  swaps its "No significant issues detected." line for the
  EmptyZeroFindings rendering with the next-move nudge.

Track 10.8 — Visual regression goldens (foundation)
  New `testdata/empty_state_goldens/<kind>.txt` — seven byte-for-
  byte golden files matching the seven shipped EmptyStateKind
  values. Companion test `TestEmptyState_Goldens` asserts byte
  equality on every kind. The drift gate
  `TestEmptyState_GoldensCoverEveryKind` verifies that the goldens
  directory matches the shipped enum 1:1 — adding a new kind
  without a golden, or vice versa, fails CI.

  Running `go test ./internal/reporting/... -update-empty-state-goldens`
  regenerates the goldens after intentional copy changes.

  This is the foundation for the broader Track 10.8 visual
  regression suite — once Track 10.2-10.4 (renderer migration to
  uitokens) lands, the same golden pattern extends to
  PR-comment markdown, SARIF tags, and HTML report screenshots.

Verification: 11 new tests pass; full Go test suite green; no
regression in existing renderers.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 2, 2026

[RISK] Terrain — Merge with caution

High-severity gaps found in changed code.

Metric Value
Changed files 11 (2 source · 3 test)
Impacted units 6
Protection gaps 2
Tests selected 2 of 774 (0% of suite)

Coverage gaps in changed code

  • internal/reporting/empty_states.go [MED] — Exported function EmptyState has no observed test coverage.
    → Add unit tests for exported function EmptyState — this is public API surface.
  • internal/reporting/insights_report_v2.go [MED] — Exported function RenderInsightsReport has no observed test coverage.
    → Add unit tests for exported function RenderInsightsReport — this is public API surface.

Pre-existing issues (2)

  • internal/reporting/empty_states.go [HIGH] — [blastRadiusHotspot] Changes to this file propagate to 1801 tests (120 direct, 1681 indirect). High blast radius increases regression risk.
  • internal/reporting/insights_report_v2.go [HIGH] — [blastRadiusHotspot] Changes to this file propagate to 1801 tests (120 direct, 1681 indirect). High blast radius increases regression risk.

Recommended tests

2 test(s) with exact coverage of 4 impacted unit(s). 2 impacted unit(s) have no covering tests in the selected set.

Test Confidence Why
internal/reporting/empty_state_goldens_test.go exact exact coverage of EmptyStateKind, RenderEmptyState
internal/reporting/empty_states_test.go exact exact coverage of EmptyStateFor, EmptyStateMarkdown

Owners: PMCLSF

Limitations
  • No coverage artifacts provided; protection gaps reflect missing data, not measured absence. Provide --coverage to improve accuracy.
  • Mixed test cultures reduce cross-framework optimization confidence. Consider standardizing on fewer frameworks.

Generated by Terrain · terrain pr --json for machine-readable output

Targeted Test Results

Terrain selected 2 test(s) instead of the full suite.

  • Go tests: passed

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 2, 2026

Terrain AI Risk Review

Metric Value
AI surfaces 13
Eval scenarios 16
Impacted scenarios 0
Uncovered surfaces 13

Decision: PASS — AI surfaces are covered.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant