Skip to content

test(mecatui): stabilize streaming Markdown ANSI parity - #2673

Merged
jbeda merged 2 commits into
mainfrom
fix/2661-stream-markdown-parity
Nov 3, 2026
Merged

jbeda merged 2 commits into
mainfrom
fix/2661-stream-markdown-parity

Conversation

@jbeda

@jbeda jbeda commented Nov 3, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes #2661.

  • Compare streaming/full Markdown output by effective ANSI style after the existing Chroma foreground-colour masking, rather than by incidental SGR run boundaries.
  • Use the existing ANSI parser and Ultraviolet style implementation; leave production rendering and dependency pins unchanged.
  • Add deterministic regression cases for the reported builtin/text regrouping and palette ties, plus negative controls preserving text, wrapping, padding, foreground presence, bold/italic/underline, attribute resets, backgrounds, glamour truecolour, style placement, final pen state, and hyperlinks.

Investigation and root-cause evidence

The palette-map tie is real, but it does not explain the reported token-run grouping: Chroma coalesces tokens before palette selection, and its terminal formatter writes each token separately.

A stronger mechanism is Chroma's regex timeout handling. In v2.27.0, regex matches have a 250 ms timeout, but matchRules silently treats matching errors as failed matches. If Bash's builtin rule times out on echo step 0\n, the generic text rule consumes echo, and Coalesce merges it with step:

normal:   NameBuiltin("echo"), Text(" step "), LiteralNumber("0")
timeout:  Text("echo step "), LiteralNumber("0")

With scratch-only copies of Chroma and regexp2, a controlled 600 ms pause after the timeout watch starts for the second builtin match makes the real regex timeout fire. Instrumentation records that error, and two full renders of the original 37-byte prefix at width 24 diverge at byte 347, exactly matching the issue's signature. Incremental rendering is not needed. The same controlled timeout passes with this comparison fix.

Evidence boundary: this establishes a matching failure mechanism on current-main dependencies, not retrospective proof of which regex timed out in the original uninstrumented run. Before the fix, 100 focused non-race repetitions and five repetitions of all streaming Markdown tests under race passed naturally; those passes do not establish that the dependency upgrade fixed the flake. No natural current-main reproduction was captured. An exploratory process-pause run timed out without a parity assertion and is not counted as flake evidence.

Scope of the fix

The test already intentionally discarded Chroma foreground-colour differences. It now also ignores changes in run segmentation that become equivalent after that masking. Meaningful differences outside that existing colour exclusion still fail.

This fixes the parity test's comparison contract, not Chroma's upstream timeout/error policy. Real syntax highlighting can still change under a lexer timeout; that production behaviour is not changed here. Other attribute changes, including those caused by lexer timeouts, remain observable to the parity test.

Validation

All final gates passed on this change:

  • timeout 1800 task --concurrency 3 test
  • timeout 1800 task --concurrency 3 test:race
  • timeout 600 task lint — zero issues across all modules
  • GOWORK=off go run ./cmd/mecademo — tool call/result and permission ask/approval present
  • GOMAXPROCS=2 GOWORK=off go test -race ./cmd/mecatui/ui -run '^TestNormalizeMarkdownANSI$|^TestStreamMarkdownMatchesFullRender/heading_and_fence_runs$' -count=25 -timeout=300s — passed in 103.061s
  • Controlled-timeout reproduction: failed with the original comparison at byte 347; passed with effective-style comparison
  • Regression mutation: restoring the original palette-only mask makes the permanent builtin-regrouping case fail deterministically
  • Negative-control mutation: replacing normalization with ansi.Strip makes all 11 styling/link negative controls fail
  • git diff --check

Initial lint and repeated-race attempts exhausted their outer budgets while full gates were compiling concurrently, without parity assertions. Both were rerun successfully after the full suites finished.

API compatibility

Test-only change. No remote-observable behaviour, wire/API contracts, Go public APIs, stored data, feature identifiers, or API major changes. No upgrade implications.

jbeda and others added 2 commits November 3, 2026 08:53
Normalize equivalent SGR runs after Chroma foreground masking to avoid the streaming parity flake in #2661. Preserve regression coverage for text, layout, styling, links, and final pen state.

Co-authored-by: Mecatl <noreply@mecatl.dev>
Record the direct import added by the Markdown ANSI parity tests so module tidy leaves the checkout clean.

Co-authored-by: Mecatl <noreply@mecatl.dev>
@jbeda
jbeda enabled auto-merge (squash) November 3, 2026 17:10
@jbeda
jbeda merged commit 1c085bb into main Nov 3, 2026
45 checks passed
@jbeda
jbeda deleted the fix/2661-stream-markdown-parity branch November 3, 2026 17:21
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.

flake(mecatui): streaming Markdown parity intermittently differs in ANSI token runs

1 participant