🐹 Go Fan Report: charmbracelet/x/exp/golden
Module Overview
github.com/charmbracelet/x/exp/golden is a tiny but essential testing helper from the Charmbracelet x monorepo. It provides golden-file assertions for tests that produce terminal output (or any text), with automatic escape-sequence handling and a -update flag for regenerating fixtures. The package surface is intentionally minimal — one generic function (RequireEqual[T []byte | string]) does all the work.
- Version pinned:
v0.0.0-20260503005035-c113ba3d2310 (Go pseudo-version; subpackage has no tagged releases)
- Repo last push: 2026-05-19 (top of the round-robin sort today, though
exp/golden itself has been stable since 2026-03-09)
- Selected via: round-robin priority by
pushed_at desc, skipping modelcontextprotocol/go-sdk (reviewed 2026-05-18)
Current Usage in gh-aw
- Go test files: 2 (
pkg/console/golden_test.go, pkg/workflow/wasm_golden_test.go)
- Call sites: 8 (all
golden.RequireEqual, all passing string)
- Golden files on disk: 52 under
pkg/{console,workflow}/testdata/
- Wire-up: Makefile targets
update-golden, update-wasm-golden, test-wasm-golden; sister Node.js script scripts/test-wasm-golden.mjs
- Deprecated API usage: none —
RequireEqualEscape is correctly unused ✅
Research Findings
Recent Updates
- 2025-06-02 —
feat(exp/golden): accept strings on RequireEqual introduced the generic T []byte | string parameter (the project already uses it)
- 2025-02-07 — Windows
\r\n → \n normalisation fix
- 2024-11-18 — always show escaped golden files when comparing outputs
- 2024-05-21 — initial escape-sequence support
The exp/golden subpackage has been stable for ~14 months. The repo-wide pushed_at (2026-05-19) is driven by activity in other subpackages (ansi, cellbuf, ultraviolet).
Best Practices (from upstream)
- Use generic
RequireEqual (do not call deprecated RequireEqualEscape)
- Subtest names become path components: avoid
/ in t.Run names
- Wire the
-update flag into a Makefile target so contributors don't have to remember the magic incantation
- Normalise non-deterministic output (timestamps, randomised tokens, digests) before comparison — already a pattern in
wasm_golden_test.go:normalizeOutput
Improvement Opportunities
🏃 Quick Wins
1. Delete 15 orphaned .golden files (4 directories, no matching tests).
The test functions exist only as stub comments in pkg/console/golden_test.go:132,320,322:
| Directory |
Files |
Status |
pkg/console/testdata/TestGolden_LayoutBoxRendering/ |
3 |
no test function |
pkg/console/testdata/TestGolden_LayoutComposition/ |
3 |
no test function |
pkg/console/testdata/TestGolden_LayoutEmphasisBox/ |
4 |
no test function |
pkg/console/testdata/TestGolden_TreeRendering/ |
5 |
no test function |
Either restore the tests (the golden files contain the expected output already!) or delete the dead fixtures and the stub comments at golden_test.go:132,320,322.
✨ Feature Opportunities
2. Lock down TestWasmGolden_AllEngines with golden files.
The test at pkg/workflow/wasm_golden_test.go:265-317 currently only checks require.Contains(yamlOutput, "name:") / "on:" / "jobs:" per engine. Engine routing has been a regression hotspot before; a per-engine golden file (one for copilot, claude, codex, gemini, pi) would catch differences earlier at zero runtime cost. The normalisation helper normalizeOutput is already available.
3. Parallelise TestWasmGolden_CompileFixtures.
The subtest body at pkg/workflow/wasm_golden_test.go:62-103 does os.Chdir(absFixturesDir) and then os.Chdir(origDir) immediately before golden.RequireEqual. Because golden.RequireEqual resolves testdata/ relative to the process working directory (global state), t.Parallel() is unsafe today. Two paths forward:
- Refactor to pass absolute paths to the compiler (the existing
compiler.CompileToYAML(wd, fixture) accepts a filename arg) so the os.Chdir dance can be removed → then add t.Parallel().
- If
os.Chdir is truly required, add a comment documenting why parallelism is disabled.
📐 Best Practice Alignment
4. Output normalisation is already well done ✅. normalizeOutput() in pkg/workflow/wasm_golden_test.go:24-27 strips Docker @sha256: pins, AWF image-tag digests, and randomised heredoc delimiters before the golden comparison. This pattern matches upstream guidance and should be preserved.
5. Document the subtest-name convention. pkg/console/golden_test.go consistently uses snake_case subtest names ("simple_table", "wide_table") because subtests with / create unwanted subdirectories under testdata/. A one-line comment in the file header would prevent accidental t.Run("foo/bar", ...) calls from someone unfamiliar with the package's path semantics.
🔧 General Improvements
6. Track skipped wasm fixtures. t.Skipf in wasm_golden_test.go:84,90 silently drops fixtures that fail ParseWorkflowString or CompileToYAML. A single summary t.Logf("WasmGolden skipped %d/%d fixtures", ...) per parent test would surface coverage regressions over time.
7. Pseudo-version refresh cadence. The dependency is pinned by pseudo-version (v0.0.0-20260503005035-...) since exp/golden has no tagged releases for the subpackage. Periodically run go get -u github.com/charmbracelet/x/exp/golden@latest (e.g., via Dependabot which already runs in this repo) to pick up upstream fixes like Windows line-break handling.
Recommendations (prioritised)
- Delete the 15 orphaned
.golden files (or restore the tests) — pure cleanup, no risk. Stub comments in pkg/console/golden_test.go:132,320,322 should go away too.
- Add per-engine golden files to
TestWasmGolden_AllEngines — high value, low cost, follows the existing pattern.
- Investigate removing the
os.Chdir dance in TestWasmGolden_CompileFixtures so it can run with t.Parallel() — bigger refactor but unlocks faster CI.
- Add a one-line comment about subtest-name conventions at the top of
pkg/console/golden_test.go.
Next Steps
References
Generated by Go Fan 🐹
Module summary saved to: scratchpad/mods/charmbracelet-x-exp-golden.md
Generated by 🐹 Go Fan · ● 10M · ◷
🐹 Go Fan Report:
charmbracelet/x/exp/goldenModule Overview
github.com/charmbracelet/x/exp/goldenis a tiny but essential testing helper from the Charmbraceletxmonorepo. It provides golden-file assertions for tests that produce terminal output (or any text), with automatic escape-sequence handling and a-updateflag for regenerating fixtures. The package surface is intentionally minimal — one generic function (RequireEqual[T []byte | string]) does all the work.v0.0.0-20260503005035-c113ba3d2310(Go pseudo-version; subpackage has no tagged releases)exp/goldenitself has been stable since 2026-03-09)pushed_atdesc, skippingmodelcontextprotocol/go-sdk(reviewed 2026-05-18)Current Usage in gh-aw
pkg/console/golden_test.go,pkg/workflow/wasm_golden_test.go)golden.RequireEqual, all passingstring)pkg/{console,workflow}/testdata/update-golden,update-wasm-golden,test-wasm-golden; sister Node.js scriptscripts/test-wasm-golden.mjsRequireEqualEscapeis correctly unused ✅Research Findings
Recent Updates
feat(exp/golden): accept strings on RequireEqualintroduced the genericT []byte | stringparameter (the project already uses it)\r\n→\nnormalisation fixThe
exp/goldensubpackage has been stable for ~14 months. The repo-widepushed_at(2026-05-19) is driven by activity in other subpackages (ansi,cellbuf,ultraviolet).Best Practices (from upstream)
RequireEqual(do not call deprecatedRequireEqualEscape)/int.Runnames-updateflag into a Makefile target so contributors don't have to remember the magic incantationwasm_golden_test.go:normalizeOutputImprovement Opportunities
🏃 Quick Wins
1. Delete 15 orphaned
.goldenfiles (4 directories, no matching tests).The test functions exist only as stub comments in
pkg/console/golden_test.go:132,320,322:pkg/console/testdata/TestGolden_LayoutBoxRendering/pkg/console/testdata/TestGolden_LayoutComposition/pkg/console/testdata/TestGolden_LayoutEmphasisBox/pkg/console/testdata/TestGolden_TreeRendering/Either restore the tests (the golden files contain the expected output already!) or delete the dead fixtures and the stub comments at
golden_test.go:132,320,322.✨ Feature Opportunities
2. Lock down
TestWasmGolden_AllEngineswith golden files.The test at
pkg/workflow/wasm_golden_test.go:265-317currently only checksrequire.Contains(yamlOutput, "name:")/"on:"/"jobs:"per engine. Engine routing has been a regression hotspot before; a per-engine golden file (one forcopilot,claude,codex,gemini,pi) would catch differences earlier at zero runtime cost. The normalisation helpernormalizeOutputis already available.3. Parallelise
TestWasmGolden_CompileFixtures.The subtest body at
pkg/workflow/wasm_golden_test.go:62-103doesos.Chdir(absFixturesDir)and thenos.Chdir(origDir)immediately beforegolden.RequireEqual. Becausegolden.RequireEqualresolvestestdata/relative to the process working directory (global state),t.Parallel()is unsafe today. Two paths forward:compiler.CompileToYAML(wd, fixture)accepts a filename arg) so theos.Chdirdance can be removed → then addt.Parallel().os.Chdiris truly required, add a comment documenting why parallelism is disabled.📐 Best Practice Alignment
4. Output normalisation is already well done ✅.
normalizeOutput()inpkg/workflow/wasm_golden_test.go:24-27strips Docker@sha256:pins, AWF image-tag digests, and randomised heredoc delimiters before the golden comparison. This pattern matches upstream guidance and should be preserved.5. Document the subtest-name convention.
pkg/console/golden_test.goconsistently usessnake_casesubtest names ("simple_table", "wide_table") because subtests with/create unwanted subdirectories undertestdata/. A one-line comment in the file header would prevent accidentalt.Run("foo/bar", ...)calls from someone unfamiliar with the package's path semantics.🔧 General Improvements
6. Track skipped wasm fixtures.
t.Skipfinwasm_golden_test.go:84,90silently drops fixtures that failParseWorkflowStringorCompileToYAML. A single summaryt.Logf("WasmGolden skipped %d/%d fixtures", ...)per parent test would surface coverage regressions over time.7. Pseudo-version refresh cadence. The dependency is pinned by pseudo-version (
v0.0.0-20260503005035-...) sinceexp/goldenhas no tagged releases for the subpackage. Periodically rungo get -u github.com/charmbracelet/x/exp/golden@latest(e.g., via Dependabot which already runs in this repo) to pick up upstream fixes like Windows line-break handling.Recommendations (prioritised)
.goldenfiles (or restore the tests) — pure cleanup, no risk. Stub comments inpkg/console/golden_test.go:132,320,322should go away too.TestWasmGolden_AllEngines— high value, low cost, follows the existing pattern.os.Chdirdance inTestWasmGolden_CompileFixturesso it can run witht.Parallel()— bigger refactor but unlocks faster CI.pkg/console/golden_test.go.Next Steps
References
scratchpad/visual-regression-testing.mdscratchpad/mods/charmbracelet-x-exp-golden.md/tmp/gh-aw/cache-memory/state.jsonGenerated by Go Fan 🐹
Module summary saved to:
scratchpad/mods/charmbracelet-x-exp-golden.md