Skip to content

fix: pass structured arguments to shared Go and Make MCP tools - #67894

Merged
pelikhan merged 7 commits into
mainfrom
pelikhan-shellcheck-argument-wrappers
Oct 12, 2026
Merged

pelikhan merged 7 commits into
mainfrom
pelikhan-shellcheck-argument-wrappers

Conversation

@pelikhan

@pelikhan pelikhan commented Oct 12, 2026 •

Copy link
Copy Markdown
Collaborator

Why

The shared Go/Make MCP wrappers used unquoted argument strings, causing SC2086 warnings, accidental globbing, and incorrect handling of paths with spaces. Replace the ambiguous command-string interface with explicit argument arrays, without Python or shell evaluation.

Approach

  • mcpscripts-go and mcpscripts-make now require args arrays of strings, for example {"args":["test","./..."]} or {"args":["build","-o","path with spaces/output"]}. Existing string calls must migrate to arrays; shell quoting should not be added to array elements.
  • JavaScript handlers invoke Node's execFile directly. Invalid inputs fail before command execution. Output and command failures use the existing MCP result shape and shared error formatter, retaining stdout, stderr, and exit-code diagnostics.
  • Update all authored caller examples and recompile both importing workflow locks. Regression tests execute the generated JavaScript handlers and cover multiple arguments/targets, spaces, literal quotes/backslashes, empty arguments, glob/shell syntax, rejected inputs, command failures, missing executables, and emitted array schemas.

This branch starts from main and remains independent of #67811. No Claude network/domain changes, ShellCheck suppressions, eval, Python dependency, or live workflow runs are included.

Validation

  • make build and make fmt passed.
  • Targeted shared-wrapper and related MCP parsing/generation Go tests passed.
  • All 41 tests in the existing JavaScript MCP handler, shared process helper, and runner suites passed. On macOS, the test invocation used a canonical TMPDIR to avoid the existing /var versus /private/var path assertion mismatch.
  • make recompile compiled all 337 workflows.
  • make agent-report-progress passed formatting, change-scoped lint, impacted tests, schema freshness, and workflow drift checks.
  • ./gh-aw compile smoke-claude daily-cli-performance --strict --shellcheck --no-check-update passed ShellCheck across 160 run-step resources.

The previously observed ignored-filesystem-policy and dry-run-only upload-sarif-removal warnings remain out of scope.

Security / scope note

The committed normal-mode generated locks do not add or remove secrets, actions, container pins, or redirects. Each array element is passed literally without shell expansion. No Actions or live agent workflow was dispatched.

pelikhan and others added 2 commits October 11, 2026 22:39
Preserve the string args contract while handling POSIX quoting with shlex and executing an explicit argv without shell expansion. Add regression tests and regenerate importing workflow locks.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Replace string parsing and Python with JavaScript execFile and validated string arrays. Update all authored caller examples and regenerate workflow locks, with executable regression coverage for literal arguments and errors.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@pelikhan pelikhan changed the title fix: preserve quoted arguments in shared Go and Make MCP tools fix: pass structured arguments to shared Go and Make MCP tools Oct 12, 2026
@pelikhan
pelikhan marked this pull request as ready for review October 12, 2026 05:50
Copilot AI balanced review requested due to automatic review settings October 12, 2026 05:50
@github-actions

github-actions Bot commented Oct 12, 2026 •

Copy link
Copy Markdown
Contributor

✅ Ponytail Reviewer completed successfully!

Lean already. Ship.

Generated by Ponytail Reviewer for #67894

@github-actions

github-actions Bot commented Oct 12, 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 12, 2026 •

Copy link
Copy Markdown
Contributor

✅ PR Code Quality Reviewer completed the code quality review.

No GitHub write applied yet while investigating safeoutputs write approval failure.

🔎 Code quality review by PR Code Quality Reviewer

@github-actions

github-actions Bot commented Oct 12, 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 12, 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

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

The generated schemas omit string item constraints for both argument arrays.

1 open finding
What changed in this PR

Migrates shared Go/Make MCP tools from shell-split strings to literal argument arrays, preventing globbing and quoting errors.

Changes:

  • Uses Node execFile with validated string arrays.
  • Updates callers, documentation, generated locks, and regression tests.
  • Preserves existing permissions, dependencies, and network access.
File Description
.github/​workflows/​shared/​go-make.md Defines array-based Go/Make handlers.
.github/​workflows/​smoke-claude.md Updates Make invocation syntax.
.github/​workflows/​smoke-claude.lock.yml Recompiles the smoke workflow.
.github/​workflows/​daily-cli-performance.md Updates MCP examples.
.github/​workflows/​daily-cli-performance.lock.yml Recompiles the performance workflow.
pkg/​workflow/​shared_go_make_test.go Tests literal arguments and failures.

🧠 Review effort: Balanced


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

Comment thread .github/workflows/shared/go-make.md
@github-actions

Copy link
Copy Markdown
Contributor

🏗️ Design Decision Gate — ADR Required

This PR makes significant changes to core business logic (>100 new lines in pkg/) but does not have a linked Architecture Decision Record (ADR).

📄 Draft ADR committed: docs/adr/67894-structured-argument-arrays-for-shared-mcp-script-tools.md — review and complete it before merging.

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

📊 Why this gate triggered
  • Business-logic additions: 159 (threshold: 100) — pkg/workflow/shared_go_make_test.go
  • implementation label: not present (triggered by code volume)
  • No ADR link found in the PR body, no matching file in docs/adr/, and no closing-keyword issue reference to check
🏗️ Decision captured in the draft

Decision: change the args input of mcpscripts-go / mcpscripts-make from an opaque shell-interpreted string to an array of strings, and replace the generated Bash handlers with JavaScript handlers that call Node's execFile without a shell.

Alternatives documented: quote/split the string in Bash (read -ra); keep an array but execute via bash -c with printf %q quoting; suppress SC2086.

Key trade-offs: literal argument passing and fast-fail validation, at the cost of a breaking caller contract, loss of shell features (pipes, redirection, globs) through these tools, and a Node runtime requirement on the runner.

📋 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, refine the decision rationale, and list real alternatives you 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-67894: Pass Structured Argument Arrays to the Shared Go and Make MCP Tools

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

📋 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 · 49.6 AIC · ⌖ 51 AIC · ⊞ 1.8K · ◷
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.

Review summary

The structured-argv switch is directionally right, but I found two follow-up gaps before this is truly finished: the diagnostics path still assumes args is a string, and the published MCP schema now accepts arrays that the handler will still reject at runtime.

Themes
  • update tool-call/failure reporting helpers to render args: string[] instead of dropping or blobifying the command preview
  • tighten the generated input schema so it actually describes string[], or keep a compatible surface until it can

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

Comment thread .github/workflows/shared/go-make.md
Comment thread .github/workflows/shared/go-make.md

@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 and /tdd (per pr-triage classification: bug fix). No blocking issues found.

📋 Analysis

Root cause addressed, not just symptom

The old run: wrapper interpolated $INPUT_ARGS unquoted into go $INPUT_ARGS / make $INPUT_ARGS, which is exactly the SC2086 class of bug (word-splitting, globbing, injection via shell metacharacters). The fix removes the shell entirely — execFile("go", args, ...) passes each array element as a literal argv entry with no shell involved — so the root cause (shell reinterpretation of agent-supplied text) is eliminated, not papered over with quoting.

Regression test quality

pkg/workflow/shared_go_make_test.go is a strong regression suite: it reads the actual go-make.md frontmatter, generates the real JavaScript handler via GenerateMCPScriptJavaScriptToolScript, and executes it as a genuine subprocess against a stub go/make binary that records process.argv. Coverage includes spaces, quotes/backslashes, empty strings, embedded whitespace, literal globs, literal shell metacharacters ($(...), backticks, ;, >, ~), invalid input shapes, non-zero exit codes, and missing executables (ENOENT). This directly exercises the injection scenarios the fix targets (e.g. test.name == "literal shell syntax" asserts injected file is never created), which is exactly the kind of instrumentation /diagnosing-bugs calls for around error/edge paths.

Consistency across the three touched Markdown docs

go-make.md, daily-cli-performance.md, and smoke-claude.md were all updated in lockstep with the new array-style examples, and both dependent .lock.yml files were recompiled — verified locally that go test ./pkg/workflow/... -run TestSharedGoMake passes cleanly against the committed HEAD.

Minor, non-blocking observation

The tool-level timeout (default 60s) is unchanged and still enforced by the shared executeProcess helper via child_process timeout option — worth being aware that long-running go test ./... or make agent-finish invocations through the MCP tool (vs. bash) could still hit that ceiling, but this is pre-existing behavior outside this PR's scope.

✅ Positive highlights
  • Clean elimination of shell involvement — no eval, no partial quoting hacks, no Python shim.
  • Reuses the existing shared buildEnhancedError helper for consistent error formatting (exit code/signal/stdout/stderr) across tool types.
  • Validates args shape explicitly before spawning the subprocess, failing fast with a clear message instead of a confusing shell error.
  • Test harness copies the real mcp-scripts-runner.cjs / mcp_handler_process.cjs / error_helpers.cjs helpers rather than mocking them, so it validates the actual generated artifact end-to-end.

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

Publish array item types through parsing, imported tools, and generated schemas. Preserve literal argument boundaries in command previews and MCP log summaries, with schema and diagnostics regression coverage.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
@pelikhan

Copy link
Copy Markdown
Collaborator Author

@copilot merge main, fix conflicts, add Tess

pelikhan and others added 3 commits October 12, 2026 04:59
Reuse diagnostic sanitization for server logs and summaries, retain tool metadata, and leave protocol responses unchanged.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
…rgument-wrappers

# Conflicts:
#	.github/workflows/daily-cli-performance.lock.yml
#	.github/workflows/smoke-claude.lock.yml

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
…ppers' into pelikhan-shellcheck-argument-wrappers

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
@pelikhan
pelikhan merged commit aeb4d6b into main Oct 12, 2026
6 checks passed
@pelikhan
pelikhan deleted the pelikhan-shellcheck-argument-wrappers branch October 12, 2026 12:08

Copilot AI commented Oct 12, 2026

Copy link
Copy Markdown
Contributor

@copilot merge main, fix conflicts, add Tess

Merged main and regenerated the two conflicting workflow locks from the merged Markdown. The merge is 498627e6; I also preserved the remote MCP diagnostic-redaction commit in 39bbf3a4. Existing argument and MCP regression tests passed (including 640 impacted JS tests; 3 skipped).

@github-actions

Copy link
Copy Markdown
Contributor

🎉 This pull request is included in a new release.

Release: v0.91.9

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.

3 participants