Skip to content

Bound MCP compile failure diagnostics without losing actionable errors - #67424

Merged
pelikhan merged 3 commits into
mainfrom
pelikhan-bound-mcp-compile-errors
Oct 10, 2026
Merged

pelikhan merged 3 commits into
mainfrom
pelikhan-bound-mcp-compile-errors

Conversation

@pelikhan

@pelikhan pelikhan commented Oct 10, 2026 •

Copy link
Copy Markdown
Collaborator

Closes #66823. Corroborating reports: #66455, #66792, #67119, #67350.

ADR: ADR-67424: Bound MCP Compile Diagnostics With a Streaming Head/Tail Collector. Completed for maintainer review; status remains Proposed until review and merge.

Changes

  • Drain compile stderr through a compile-local streaming collector rather than buffering debug floods. Retain cause-first errors, multiline remediation, ANSI-normalized diagnostics, and explicit omission markers.
  • Limit execution-failure messages to 4 KiB and serialized fallback JSON to 48 KiB, including JSON escaping. Preserve per-workflow invalid results when they fit; otherwise return an explicit invalid batch compile result with the affected workflow count.
  • Preserve structured compiler/scanner JSON, even when it exceeds the fallback budget or the subprocess exits nonzero. Collect shellcheck findings separately so normal scanner diagnostics remain available. Strict validation, required shellcheck checks, and the deprecated/ignored max_tokens contract are unchanged.
  • Match debug lines by the logger's namespace/message/elapsed format, without a fixed namespace allowlist. Preserve the active error block across interleaved debug lines. Shellcheck headers and finding lines cannot replace the cause or dependency warning.
  • Add regressions using a real child process with DEBUG enabled and 12 MiB stderr; cover huge single lines, whitespace stdout, multiline/ANSI diagnostics, Unicode and byte boundaries, escape-heavy JSON, 334-workflow discovery, spawn failures, cancellation, concurrent request isolation, interleaved remediation, unlisted logger namespaces, and scanner/warning separation. No diagnostic-file persistence is needed.
  • Document the fallback contract and add a patch changeset.

Validation

Validated the code committed as 63248a5ea648fa7ab7dac048f4052db0451e2fd0:

  • npm_config_package=prettier@3.9.9 PATH="/opt/homebrew/bin:$(go env GOPATH)/bin:$PATH" make fmt — passed.
  • npm_config_package=prettier@3.9.9 PATH="/opt/homebrew/bin:$(go env GOPATH)/bin:$PATH" make lint — passed, including full-repository Go lint, JavaScript lint, shellcheck and schema checks. Existing JavaScript warnings remain warnings; no rules were disabled.
  • npm_config_package=prettier@3.9.9 PATH="/opt/homebrew/bin:$(go env GOPATH)/bin:$PATH" make agent-report-progress — passed, including build, changed-file standard/custom Go lint, impacted unit tests and workflow drift (all 334 workflow lock files in sync). Existing custom analyzer findings in unchanged files are handled by the repository's change-scoped gate.
  • go test ./pkg/cli -run 'Test(CompileTool|MCPCompile|BuildCompileErrorResults|InjectShellcheckDiagnostics|InjectDockerUnavailableWarning|ExtractLastConsoleMessage|DevelopmentCompileFailsWithoutShellcheckOrDocker|MCPSubprocessGuardrail)' -count=1 — passed.
  • go test -race ./pkg/cli -run 'Test(MCPCompile|CompileToolBounds|CompileToolPreservesStructuredFailureAfterDebugFlood|CompileToolDevelopmentPreservesBatchDiagnosticsOnFailure|CompileTool_UsesOnlyStdoutOnSuccess)' -count=1 — passed.
  • git diff --check — passed.

The new review regressions reproduced the defects before the fixes and pass afterward. All five in-scope review threads were replied to and resolved.

Earlier publication encountered a shared golangci-lint lock and baseline custom-linter findings; the finishing pass's required local gates now pass. The default unpinned npx selected Prettier 4.0.0-alpha.13 and crashed on unrelated JSON; the declared dependencies and pinned Prettier 3.9.9 are used for validation without unrelated formatting changes.

CI hand-off: the two last-known CI checks were successful at triage. CI on the latest agent-pushed HEAD remains unverified until a maintainer re-triggers it. No Actions runs were triggered and the PR was not merged.

Preserve actionable dependency errors and scanner results while limiting fallback diagnostics to 4 KiB and fallback JSON to 48 KiB.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@pelikhan
pelikhan marked this pull request as ready for review October 10, 2026 12:06
Copilot AI balanced review requested due to automatic review settings October 10, 2026 12:07
@github-actions

github-actions Bot commented Oct 10, 2026 •

Copy link
Copy Markdown
Contributor

✅ PR Code Quality Reviewer completed the code quality review.

Testing safeoutputs availability after bash write denial.

🔎 Code quality review by PR Code Quality Reviewer

@github-actions

github-actions Bot commented Oct 10, 2026 •

Copy link
Copy Markdown
Contributor

✅ Test Quality Sentinel completed test quality analysis.

Test Quality Sentinel skipped because pre-fetch PR data was unavailable: unable to fetch test file diff

🧪 Test quality analysis by Test Quality Sentinel

@github-actions

github-actions Bot commented Oct 10, 2026 •

Copy link
Copy Markdown
Contributor

✅ Design Decision Gate 🏗️ completed the design decision gate check. See the comment below for the result and any generated ADR draft.

🏗️ ADR gate enforced by Design Decision Gate 🏗️

@github-actions

github-actions Bot commented Oct 10, 2026 •

Copy link
Copy Markdown
Contributor

✅ Ponytail Reviewer completed successfully!

Lean already. Ship.

Generated by Ponytail Reviewer for #67424

@github-actions

github-actions Bot commented Oct 10, 2026 •

Copy link
Copy Markdown
Contributor

🧠 Matt Pocock Skills Reviewer has completed the skills-based review. ✅

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer

@github-actions

Copy link
Copy Markdown
Contributor

🏗️ Design Decision Gate — ADR Required

This PR makes significant changes to core business logic (507 new lines in pkg/, above the 100-line default threshold) but does not have a linked Architecture Decision Record (ADR).

📄 Draft ADR committed: docs/adr/67424-bound-mcp-compile-diagnostics-with-streaming-collector.md — review and complete it before merging.

🔒 This PR cannot merge until an ADR is linked in the PR body.

🔎 Evidence used
  • Labels: none (implementation label not present) — enforcement triggered by code volume.
  • Business-logic additions: 507 (pkg/cli/mcp_compile_diagnostics.go +207, pkg/cli/mcp_compile_diagnostics_test.go +294, pkg/cli/mcp_tools_readonly.go +6/-22).
  • No .design-gate.yml found — default directories and 100-line threshold applied.
  • No ADR link or ADR section found in the PR body; no docs/adr/67424-*.md existed on the branch.
  • Decision inferred from the new streaming head/tail diagnostic collector and the 4 KiB / 48 KiB bounds in pkg/cli/mcp_compile_diagnostics.go.
📋 What to do next
  1. Review the draft ADR committed to your branch — it was generated from the PR diff
  2. Complete the missing sections — add context the AI couldn't infer (notably the full list of deciders), refine the decision rationale, and confirm the alternatives listed match what you actually considered
  3. Commit the finalized ADR to docs/adr/ on your branch
  4. Reference the ADR in this PR body by adding a line such as:

    ADR: ADR-67424: Bound MCP Compile Diagnostics With a Streaming Head/Tail Collector

Once an ADR is linked in the PR body, this gate will re-run and verify the implementation matches the decision.

❓ Why ADRs Matter

ADRs 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 Reference

An ADR must contain these four sections to be considered complete:

  • Context — What is the problem? What forces are at play?
  • Decision — What did you decide? Why?
  • Alternatives Considered — What else could have been done?
  • Consequences — What are the trade-offs (positive and negative)?

All ADRs are stored in docs/adr/ as Markdown files numbered by PR number.

🏗️ ADR gate enforced by Design Decision Gate 🏗️ · pi · opus50 · 39.4 AIC · ⌖ 45.9 AIC · ⊞ 1.8K · ◷
Comment /review to run again

@github-actions

Copy link
Copy Markdown
Contributor

Comment Memory

Peek at saved memory (pr-code-quality-reviewer)
reviewed_at: 2026-10-10T12:09:31Z
review_event: REQUEST_CHANGES
top_themes:
  - multiline diagnostic parsing under debug-log interleaving
files_reviewed:
  - docs/src/content/docs/reference/gh-aw-as-mcp-server.md
  - pkg/cli/mcp_compile_diagnostics.go
  - pkg/cli/mcp_compile_diagnostics_test.go
  - pkg/cli/mcp_tools_readonly.go
comment_count: 1

Note

This comment is managed by comment memory.

Expand the saved memory block to view or edit the persistent context for this thread.
Edit only the text inside the backtick fences; workflow metadata and the footer are regenerated automatically.

Learn more about comment memory

🔎 Code quality review by PR Code Quality Reviewer · copilot · gpt54 · 39.8 AIC · ⌖ 5.57 AIC · ⊞ 20K · ◷
Comment /review to run again

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Request changes

The new stderr collector is on the right track, but it still drops remediation text when debug output is interleaved between the error line and its follow-up details. That leaves the fallback JSON with the least actionable part of the failure in exactly the noisy-debug scenario this patch is meant to harden.

The blocking theme
  • Skipping a workflow: / cli: debug line currently clears the active multiline error block, so later remediation lines are discarded instead of being preserved.

🔎 Code quality review by PR Code Quality Reviewer · copilot · gpt54 · 39.8 AIC · ⌖ 5.57 AIC · ⊞ 20K
Comment /review to run again

Comment thread pkg/cli/mcp_compile_diagnostics.go Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Diagnostic classification misses valid logger namespaces and console prefixes, allowing non-actionable output into failure responses.

1 open finding
What changed in this PR

Bounds MCP compile-failure diagnostics while preserving actionable and structured scanner output.

Changes:

  • Adds streaming stderr collection and bounded fallback JSON.
  • Adds regression coverage for large, malformed, and concurrent diagnostics.
  • Documents the fallback contract and release impact.
File Description
pkg/​cli/​mcp_tools_readonly.go Integrates bounded compile diagnostics.
pkg/​cli/​mcp_compile_diagnostics.go Implements streaming collection and limits.
pkg/​cli/​mcp_compile_diagnostics_test.go Tests bounds, cancellation, Unicode, and isolation.
docs/​src/​content/​docs/​reference/​gh-aw-as-mcp-server.md Documents fallback behavior.
.changeset/​bound-mcp-compile-errors.md Records the patch change.

🧠 Review effort: Balanced


💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.

Comment thread pkg/cli/mcp_compile_diagnostics.go Outdated

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Skills-Based Review 🧠

Applied /diagnosing-bugs — requesting changes on three correctness gaps in the new mcpCompileDiagnostics line classifier found through direct reproduction (pkg/cli/mcp_compile_diagnostics.go).

📋 Key Themes & Highlights

Key Themes

  • Shellcheck lines leak into the reported failure message when no ✗/error: line follows them — the switch that captures shellcheck findings in .../script: lines doesn't short-circuit before the later isError/message accumulation logic.
  • Hardcoded debug-namespace allowlist (cli:, workflow:, parser:, mcp:, agentdrain:, repoutil:, logger:, stringutil:) misses ~20 other registered logger.New(...) namespaces in the repo (e.g. console:*, gitutil:, jsonutil:, typeutil:*). Debug output from any of those leaks straight into the bounded diagnostic, reintroducing the noise this PR is meant to eliminate.
  • Warning capture is last-write-wins on any ⚠-prefixed line, so a ⚠ shellcheck findings in ... header can overwrite a genuine dependency-unavailable warning, discarding the actionable one.

All three were confirmed with isolated unit reproductions against the actual mcpCompileDiagnostics.Write/finishLine/failureMessage code paths (not just read from the diff).

Positive Highlights

  • ✅ Strong test suite already covers byte-boundary truncation, UTF-8 validity, cancellation, and concurrent request isolation — excellent /tdd discipline for the happy paths.
  • ✅ The head/tail retention strategy in compileDiagnosticText is a clean, allocation-bounded way to avoid buffering debug floods.
  • ✅ Separating shellcheck findings from the execution-failure message (so structured scanner output survives truncation) is a good design call.

Note on scope

Given the PR's stated 20-tool-call investigation budget and the diff size (~500 lines across 2 new/modified Go files), I bounded exploration to the new diagnostics module and its direct dependencies (console.FormatWarningMessage, logger.New call sites) rather than tracing every compile code path that could emit these namespaces at runtime.

@copilot please address the review comments above.

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · copilot · sonnet50 · 173.6 AIC · ⌖ 16.1 AIC · ⊞ 10.3K
Comment /matt to run again

Comment thread pkg/cli/mcp_compile_diagnostics.go
Comment thread pkg/cli/mcp_compile_diagnostics.go Outdated
Comment thread pkg/cli/mcp_compile_diagnostics.go
Recognize logger output generically, keep remediation blocks open across debug lines, and isolate shellcheck findings from failure summaries. Complete the diagnostic bounding ADR.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@pelikhan
pelikhan merged commit 1976c94 into main Oct 10, 2026
72 checks passed
@pelikhan
pelikhan deleted the pelikhan-bound-mcp-compile-errors branch October 10, 2026 12:59
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.

[AW Top 10] 05 Stop MCP compile errors embedding megabytes of stderr

2 participants