From ac113291fcbd51a14336812501a6a1463a326b81 Mon Sep 17 00:00:00 2001 From: Eric Rakestraw Date: Sat, 7 Nov 2026 15:45:37 +0000 Subject: [PATCH] Share reporter detail rendering --- docs/roadmap/audit/catalog.md | 8 ++++++-- docs/roadmap/implementation.md | 6 +++++- reporter.go | 29 ++++++++++------------------- 3 files changed, 21 insertions(+), 22 deletions(-) diff --git a/docs/roadmap/audit/catalog.md b/docs/roadmap/audit/catalog.md index b1d0127..677cb43 100644 --- a/docs/roadmap/audit/catalog.md +++ b/docs/roadmap/audit/catalog.md @@ -1,6 +1,6 @@ # Consolidated audit catalog -Status: **19 distinct open findings: 19 P3**, consolidated from 30 +Status: **18 distinct open findings: 18 P3**, consolidated from 30 numbered entries in seven audit documents. Reviewed audit state: `db732e3a1de55c844f77870e1c6db683c2685d5d`. @@ -390,6 +390,10 @@ are selected. ## F20 — P3: Reporter message paths duplicate detail-rendering bookkeeping +**Complete.** Both message paths share detail callback and error bookkeeping; +focused reporter tests cover visibility, ordering, closed handles, and joined +render/write evidence. + Terminal and ordinary message paths repeat callback invocation, managed-writer setup, render-versus-write error classification, and first-error retention. Maintaining the same presentation policy in two branches increases the chance of @@ -406,7 +410,7 @@ fix deferred-message loss or writer retention. After correctness repairs, favor F20, then F18 and F17, while keeping F19 modest. All four use private functions and existing types, with no intended public API or CLI behavior change. The [F17–F20 analysis](remediation-analysis.md#f17f20--proportionate-private-extractions) -records the accepted scope; implementation remains pending. +records the accepted scope. **Original:** [03-complexity M7](03-complexity.md#m7--p3-terminal-and-ordinary-messages-duplicate-detail-rendering-mechanics). diff --git a/docs/roadmap/implementation.md b/docs/roadmap/implementation.md index f31dc88..8c53bc3 100644 --- a/docs/roadmap/implementation.md +++ b/docs/roadmap/implementation.md @@ -1,6 +1,6 @@ # Audit remediation implementation plan -Status: in progress; Stages 1–7 complete. +Status: in progress; Stages 1–8 complete. Baseline: `d492c7747175c01a53261206c2b4356e53453621`. Before this sprint, intervening changes recorded decisions and retired the completed older @@ -304,6 +304,10 @@ without promising immediate garbage collection or taking ownership of closers. ## Stage 8 — Share reporter detail-rendering bookkeeping +**Complete.** Terminal and ordinary reporting share detail-rendering and error +classification under the existing lock. Focused reporter and hidden-deferred +tests passed in the offline aligned Go 1.27.0 workspace with `-mod=readonly`. + Findings: F20. Source: `reporter.go`; follows lifecycle fixes in stages 3 and 7. 1. Extract a private helper running under the existing reporting lock to invoke diff --git a/reporter.go b/reporter.go index 4c38777..8625baf 100644 --- a/reporter.go +++ b/reporter.go @@ -405,21 +405,7 @@ func renderTerminalLocked(state *reportingState, explanation Explanation) error writeErr = writer.writeError } if writeErr == nil { - for _, detail := range explanation.Details { - if detail == nil { - continue - } - writer := &coordinatedWriter{state: state, destination: destinationDiagnostics} - detailErr := detail(writer) - detailWriteErr := writer.writeError - detailRenderErr := recordRendererErrorLocked(state, destinationDiagnostics, detailErr, detailWriteErr) - if renderErr == nil { - renderErr = detailRenderErr - } - if writeErr == nil { - writeErr = detailWriteErr - } - } + renderErr, writeErr = renderDetailsLocked(state, explanation.Details, true) } if renderErr == nil && writeErr == nil { destination.delivered = true @@ -469,6 +455,14 @@ func (state *reportingState) submitMessageLocked(category messageCategory, messa if visible && writeErr != nil { return writeErr } + renderErr, writeErr = renderDetailsLocked(state, details, visible) + if visible && renderErr == nil && writeErr == nil { + destination.delivered = true + } + return combineOperationErrors(renderErr, writeErr) +} + +func renderDetailsLocked(state *reportingState, details []Detail, visible bool) (renderErr, writeErr error) { for _, detail := range details { if detail == nil { continue @@ -489,10 +483,7 @@ func (state *reportingState) submitMessageLocked(category messageCategory, messa writeErr = detailWriteErr } } - if visible && renderErr == nil && writeErr == nil { - destination.delivered = true - } - return combineOperationErrors(renderErr, writeErr) + return renderErr, writeErr } func (state *reportingState) visible(category messageCategory) bool {