Repository navigation
Fix console formatter stream contracts and guard stderr usage - #67423
Conversation
Migrate proven direct stderr formatter calls with the type-aware analyzer, bound experiment human tables without truncating data, and preserve JSON, version, compact and WASM output contracts. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
|
✅ Ponytail Reviewer completed successfully! Lean already. Ship.
|
|
🧠 Matt Pocock Skills Reviewer has completed the skills-based review. ✅
|
|
✅ Test Quality Sentinel completed test quality analysis. Test Quality Sentinel skipped because pre-fetch PR data was unavailable: unable to fetch test file diff
|
|
✅ PR Code Quality Reviewer completed the code quality review.
|
|
✅ Design Decision Gate 🏗️ completed the design decision gate check. See the comment below for the result and any generated ADR draft.
|
🏗️ Design Decision Gate — ADR RequiredThis PR makes significant changes to core business logic (2,253 new lines across 241 files in 📄 Draft ADR committed:
📋 What to do next
Once an ADR is linked in the PR body, this gate will re-run and verify the implementation matches the decision. 🔍 Evidence used
❓ Why ADRs MatterADRs create a searchable, permanent record of why the codebase looks the way it does. Future contributors (and your future self) will thank you. 📋 Michael Nygard ADR Format ReferenceAn ADR must contain these four sections to be considered complete:
All ADRs are stored in
|
There was a problem hiding this comment.
🟡 Changes recommended
Three migrated warning paths still emit duplicated semantic warning prefixes.
3 open findings
What changed in this PR
This PR makes console formatting destination-aware, adds bounded human-facing tables, and enforces stderr contracts through a custom analyzer.
Changes:
- Migrates CLI, parser, and compiler diagnostics to stderr-aware formatters.
- Adds bounded, Unicode-aware table rendering for experiment output.
- Adds and CI-enforces the
consolestderranalyzer with suggested fixes.
Three warning paths still produce redundant ⚠ Warning: prefixes.
| File | Description |
|---|---|
.github/workflows/cgo.yml |
Enforces the console-stream analyzer. |
cmd/gh-aw/main.go |
Migrates help diagnostics. |
pkg/cli/*.go (174 files) |
Migrates CLI diagnostics, tables, and reflected output to stderr-aware APIs. |
pkg/cli/console_stream_contract_test.go |
Tests stream and width contracts. |
pkg/cli/experiments_fetch_test.go |
Extends the experiment API fixture. |
pkg/console/README.md |
Documents stream and width APIs. |
pkg/console/console.go |
Adds stderr formatters and bounded tables. |
pkg/console/console_types.go |
Adds width and destination options. |
pkg/console/console_wasm.go |
Preserves WASM-compatible APIs and tables. |
pkg/console/render.go |
Propagates rendering options through nested tables. |
pkg/console/stream_contract_test.go |
Tests mixed stdout/stderr terminal behavior. |
pkg/console/table_width.go |
Implements width-aware table fallback. |
pkg/console/table_width_test.go |
Tests Unicode width and losslessness. |
pkg/envutil/envutil.go |
Migrates environment warnings. |
pkg/linters/README.md |
Documents the analyzer. |
pkg/linters/consolestderr/consolestderr.go |
Implements stderr misuse detection. |
pkg/linters/consolestderr/consolestderr_test.go |
Runs analyzer suggested-fix tests. |
pkg/linters/consolestderr/testdata/src/consolestderr/consolestderr.go |
Provides analyzer findings fixture. |
pkg/linters/consolestderr/testdata/src/consolestderr/consolestderr.go.golden |
Verifies suggested fixes. |
pkg/linters/consolestderr/testdata/src/github.com/github/gh-aw/pkg/console/console.go |
Stubs console APIs for analyzer tests. |
pkg/linters/doc.go |
Registers analyzer documentation. |
pkg/linters/doc_sync_test.go |
Updates CI-enforcement expectations. |
pkg/linters/registry.go |
Registers the analyzer. |
pkg/linters/spec_test.go |
Adds analyzer documentation coverage. |
pkg/parser/include_processor.go |
Migrates include diagnostics. |
pkg/parser/workflow_update.go |
Migrates update diagnostics. |
pkg/workflow/*.go (41 files) |
Migrates compiler and validation diagnostics to stderr-aware APIs. |
🧠 Review effort: Balanced
💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.
Comment MemoryPeek at saved memory (pr-code-quality-reviewer)Note This comment is managed by comment memory.Expand the saved memory block to view or edit the persistent context for this thread.
|
There was a problem hiding this comment.
Verdict
The stream-format migration is close, but the new enforcement linter still has a bypass: RenderStructWithOptions can send stdout-styled reflected output to stderr without any diagnostic.
Blocking theme
consolestderrcoversRenderStructandRenderTable, but it does not understand the newly addedRenderStructWithOptionspath, so the guardrail this PR is introducing is still incomplete.
🔎 Code quality review by PR Code Quality Reviewer · copilot · gpt54 · 158 AIC · ⌖ 5.5 AIC · ⊞ 19.9K
Comment /review to run again
There was a problem hiding this comment.
Skills-Based Review 🧠
Applied /codebase-design on the pkg/console API surface and /tdd on the new regression coverage. The core change (stderr-aware formatter API, width-budget rendering, consolestderr analyzer) is well-designed and thoroughly tested; only two minor cleanup items found, both left as inline suggestions.
📋 Key Themes & Highlights
Key Themes
- Two small dead/redundant-code nits in
pkg/console/render.goandexperiments_render.go(see inline comments) — neither is a correctness issue. - Note on scope/trust: the pre-fetched diff was truncated at 3000 lines (53 of 241 changed files). I supplemented it with targeted API fetches of
pkg/console/*,pkg/linters/consolestderr/*,pkg/linters/registry.go, and spot-checked ~10 of the ~230 mechanical migration files inpkg/clifor pattern consistency — all sampled migrations correctly preserved streams/args/newlines. pr-triageagent invocation did not return structured output within the available context; I applied the fallback heuristic (classify directly frompr-meta.json/diff, high-impact files = non-generated files with largest delta) as instructed.
Positive Highlights
- ✅
consolestderranalyzer is type-aware (resolves imports viago/types, handles aliased imports, parenthesized expressions, suppressions via(nolint/redacted):consolestderr), with a solid golden-fixture test including a deliberate "shadowedos" false-positive guard. - ✅
stream_contract_test.go's PTY matrix (stdout/stderr TTY × NO_COLOR, 8 combinations) is a strong, direct regression test for the exact stream-contract bug class this PR fixes — a good/tddexample of testing the actual observable contract rather than internals. - ✅
table_width_test.goexplicitly asserts no data loss (counts ofx/界/qcharacters preserved) and keeps combining marks (e\u0301) intact when wrapping — this guards the opt-in width feature against the classic "silently truncates Unicode" regression. - ✅ Width budgeting is correctly scoped as opt-in (
MaxWidthzero-value keeps unbounded output); JSON/version/completion/compact-log call sites were left untouched, matching the PR's stated non-goal of a universal width change. - ✅ Documentation (
pkg/console/README.md), linter registry/README, anddoc_sync_test.go/spec_test.gowere all updated in lockstep with the new analyzer and APIs.
Acknowledged (non-blocking) scope limitation
The PR description is upfront that the analyzer doesn't trace intermediate writer/formatter aliases (dataflow). That's a reasonable, explicitly documented boundary for a mechanical migration of this size and not something to block on.
🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · copilot · sonnet50 · 183 AIC · ⌖ 16.1 AIC · ⊞ 10.3K
Comment /matt to run again
Guard explicit render destinations, remove duplicate warning prefixes and redundant rendering wrappers, and finalize the proposed ADR. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
|
Thanks for the console formatter work! 🙌 This PR is large (~4,200 lines, 246 files) and mixes several concerns (stderr migration, analyzer, width budgets, error-chain styling, table renderers). Please consider splitting it into smaller focused PRs, and note the referenced ADR still needs maintainer acceptance.
|
Undo the bulk diagnostic selector migration, preserve existing stderr aliases, and opt intentional stdout callers into explicit stdout styling. Check both output destinations without changing actual writes or machine-output contracts. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Correct scanner rendering, pin formatter callbacks, and bootstrap TODO output. Add higher-level mixed-PTY and NO_COLOR coverage for all affected paths without changing intentional stdout output or analyzer scope. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Summary
Fixes #67143 and addresses source #66976 by correcting console behavior without renaming diagnostic callers.
FormatError, message formatters,RenderTableandRenderStructdefault to stderr terminal/color detection. Existing*StderrAPIs remain compatible aliases; signatures and actual write destinations are unchanged.*Stdoutvariants. JSON, version, completion, compact logs and WASM tab-separated output retain their contracts.RenderStructWithOptionskeeps its explicit destination:Stderr: trueselects stderr; false or omitted selects stdout.consolestderranalyzer guards direct stdout/stderr writes and explicit render options. It handles imported aliases and nested expressions; intermediate writer/formatter callbacks remain outside its dataflow scope.ADR: ADR-67423: Destination-aware console formatters and stderr analyzer — Proposed; maintainer acceptance remains required.
Review follow-up
Commit
fa2c4300690fec4ac1e7c4adbbf5cd457c53c037fixes all three proven indirect stream mismatches from the review:FormatErrordefault for production stderr consumers.PinContext.emitOnceuse diagnostic defaults.No intentional stdout callers were rerouted, and the analyzer was not broadened.
TestIndirectDiagnosticStreamContractsexercises these higher-level paths with real PTYs across all eight stdout/stderr/NO_COLOR combinations. It verifies each affected callback, scanner rendering, both bootstrap messages, pin results and warning deduplication.Validation
make build,make fmt, andmake lintpass with modern Bash and cached manifest-declared Prettier 3.9.9.consolestderrpasses. Existing formatter tests cover the direct PTY/NO_COLOR matrix, nested/options tables, Unicode width/data preservation and version output; the new higher-level matrix closes the reviewed writer/callback gaps.make agent-report-progressran: impacted tests, standard lint and schema freshness pass. Its all-custom-analyzer stage still reports previously disclosed advisory debt and guarded-index false positives; no new diagnostics were reported for these fixes. No unrelated fixes or suppressions were added.