Skip to content

fix(toolset): round-trip serialized tool options#9124

Merged
jdx merged 7 commits intojdx:mainfrom
atharvasingh7007:fix/tool-option-roundtrip
Apr 16, 2026
Merged

fix(toolset): round-trip serialized tool options#9124
jdx merged 7 commits intojdx:mainfrom
atharvasingh7007:fix/tool-option-roundtrip

Conversation

@atharvasingh7007
Copy link
Copy Markdown
Contributor

Summary

  • add a shared serialize_tool_options() helper for backend and task tool specs
  • quote comma-containing string values so bracketed opts can round-trip safely
  • omit empty brackets when all remaining opts are filtered out
  • teach the legacy manual parser to respect quoted commas so mixed quoted/unquoted payloads still parse correctly

Root cause

BackendArg::full_with_opts() and TaskToolValue::to_tool_spec() both hand-rolled the same key=value formatting.

That formatting had two round-trip problems:

  1. comma-containing string values could be split into fake extra keys on the way back in
  2. when every remaining opt was an Array/Table, the task path could emit malformed empty brackets

While validating the serializer fix locally, there was one more shared-boundary issue: selectively quoting only the comma-containing value still hit the legacy manual parser whenever sibling string values stayed unquoted, so the manual parser also needed to stop splitting on commas inside quotes.

Testing

  • cargo test serialize_tool_options
  • cargo test full_with_opts
  • cargo test to_tool_spec
  • cargo test parse_tool_options

All runs were executed locally with RUSTFLAGS=-C debuginfo=0 and CARGO_INCREMENTAL=0 because this Windows machine was short on disk space during the initial build.

Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a centralized serialize_tool_options function to handle the serialization of tool options, specifically addressing issues with comma-containing strings by applying TOML-quoting. It also updates the manual parser to correctly handle these quoted values and escaped characters. The review feedback suggests simplifying the quoting logic by leveraging the Display implementation of toml::Value and extending the set of characters that trigger quoting to include brackets, which prevents potential issues with regex-based parsers. Additionally, a redundant logic block in the escaping mechanism was identified for removal.

Comment thread src/toolset/tool_version_options.rs Outdated
Comment thread src/toolset/tool_version_options.rs Outdated
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Apr 15, 2026

Greptile Summary

This PR introduces a shared serialize_tool_options() helper that correctly quotes comma-, quote-, and bracket-containing string values for safe round-tripping, refactors both BackendArg::full_with_opts() and TaskToolValue::to_tool_spec() to use it, replaces the split_bracketed_opts regex with a quote-aware char parser so brackets inside quoted values are no longer misidentified as the opts boundary, and teaches the manual parser to respect quoted commas and TOML-decode single- and double-quoted value segments.

All four concerns raised in prior review threads (missing " quoting, single-quoted value corruption, manual parser dropping keys after single-quoted segments, and empty-bracket emission for complex-only opts) are resolved in the current commit.

Confidence Score: 5/5

Safe to merge — all previously flagged round-trip bugs are resolved and the new shared serializer is well-tested.

All four concerns from prior review threads (missing quote handling, single-quote value corruption, manual parser dropping keys after single-quoted segments, and empty-bracket emission) are addressed in the current HEAD. No new P0/P1 issues were found. The quote-aware char parsers in split_bracketed_opts and split_tool_option_segments are correct, the parse_tool_option_value TOML-decode fallback is safe, and the test suite covers key edge cases including comma-in-value, bracket-in-value, and all-complex-opts scenarios.

No files require special attention.

Important Files Changed

Filename Overview
src/toolset/tool_version_options.rs Core of the fix: adds serialize_tool_options/serialize_tool_option/string_requires_tool_option_quotes, rewrites manual parser to use quote-aware split_tool_option_segments, and adds parse_tool_option_value for TOML-decoding individual value segments. Well-tested with 6 new targeted unit tests.
src/cli/args/backend_arg.rs Replaces the opts-serialization inline loop in full_with_opts() with serialize_tool_options(), and replaces the split_bracketed_opts regex with a quote-aware char parser that correctly handles brackets inside quoted option values.
src/task/mod.rs TaskToolValue::to_tool_spec() now delegates to serialize_tool_options(), fixing silent emission of malformed brackets for Array/Table-only opts and the same comma/quote round-trip bug.
src/toolset/mod.rs Re-exports serialize_tool_options from the public toolset API; one-line change.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Tool option value] --> B{Array or Table type?}
    B -- Yes --> C[Omit - cannot round-trip]
    B -- No --> D{Needs quoting?}
    D -- has comma, bracket, or quote char --> E[TOML-format the value]
    D -- plain string --> F[Emit as-is]
    E --> G[Quoted segment]
    F --> H[Serialized opts string joined by comma]
    G --> H

    H --> I{try_parse_as_toml}
    I -- success --> J[ToolVersionOptions result]
    I -- fail --> K[parse_tool_options_manual]
    K --> L[split_tool_option_segments]
    L --> M[parse_tool_option_value]
    M --> J

    H --> N[split_bracketed_opts]
    N --> O[tool name plus opts_str]
    O --> I
Loading

Reviews (4): Last reviewed commit: "[autofix.ci] apply automated fixes" | Re-trigger Greptile

Comment thread src/toolset/tool_version_options.rs Outdated
Comment thread src/toolset/tool_version_options.rs Outdated
Comment thread src/toolset/tool_version_options.rs
Comment thread src/toolset/tool_version_options.rs
@atharvasingh7007
Copy link
Copy Markdown
Contributor Author

Addressed the single-quote round-trip gap in 899d07eed.

What changed:

  • quote string option values when they contain ' as well as ,, ", [ or ]
  • added a regression test for a value like 'hi' to ensure serialize to parse preserves the surrounding single quotes

Local validation passed:

  • cargo test test_serialize_tool_options_preserves_single_quote_wrapped_strings
  • cargo test serialize_tool_options
  • cargo test parse_tool_options

@jdx jdx enabled auto-merge (squash) April 16, 2026 17:27
@jdx jdx merged commit eb75960 into jdx:main Apr 16, 2026
34 checks passed
mise-en-dev added a commit that referenced this pull request Apr 17, 2026
### 🚀 Features

- **(registry)** add .perl-version support for perl by @ergofriend in
[#9102](#9102)
- **(task)** add Tera template support for inline table run tasks by
@iamkroot in [#9079](#9079)

### 🐛 Bug Fixes

- **(env)** use runtime symlink paths for fuzzy versions by @jdx in
[#9143](#9143)
- **(github)** use full token resolution chain for attestation
verification by @jdx in [#9154](#9154)
- **(go)** Remove install-time version override for subpath packages by
@c22 in [#9135](#9135)
- **(npm)** respect install_before when resolving dist-tag versions by
@webkaz in [#9145](#9145)
- **(self-update)** ensure subcommand exists by @salim-b in
[#9144](#9144)
- **(task)** show available tasks when run target missing by @jdx in
[#9141](#9141)
- **(task)** forward task help args and add raw_args by @jdx in
[#9118](#9118)
- **(task)** remove red/yellow from task prefix colors by
@lechuckcaptain in [#8782](#8782)
- **(task)** merge TOML task block into same-named file task and surface
resolved dir by @jdx in [#9147](#9147)
- **(toolset)** round-trip serialized tool options by @atharvasingh7007
in [#9124](#9124)
- **(vfox)** fallback to absolute bin path if env_keys not set by
@80avin in [#9151](#9151)

### 📚 Documentation

- make agent guide wording generic by @jdx in
[#9142](#9142)

### 📦️ Dependency Updates

- update ghcr.io/jdx/mise:deb docker digest to e019cb9 by @renovate[bot]
in [#9160](#9160)
- update ghcr.io/jdx/mise:copr docker digest to 8d25608 by
@renovate[bot] in [#9159](#9159)
- update ghcr.io/jdx/mise:rpm docker digest to 22e52da by @renovate[bot]
in [#9161](#9161)
- update ghcr.io/jdx/mise:alpine docker digest to a3da97c by
@renovate[bot] in [#9158](#9158)
- update rust docker digest to 4a2ef38 by @renovate[bot] in
[#9162](#9162)
- update ubuntu:24.04 docker digest to c4a8d55 by @renovate[bot] in
[#9164](#9164)
- update rust crate aws-lc-rs to v1.16.3 by @renovate[bot] in
[#9165](#9165)
- update ubuntu docker tag to resolute-20260413 by @renovate[bot] in
[#9169](#9169)
- update rust crate clap to v4.6.1 by @renovate[bot] in
[#9166](#9166)
- update taiki-e/install-action digest to a2352fc by @renovate[bot] in
[#9163](#9163)
- update rust crate ctor to 0.10 by @renovate[bot] in
[#9170](#9170)
- update rust crate tokio to v1.52.1 by @renovate[bot] in
[#9167](#9167)
- update rust crate rmcp-macros to 0.17 by @renovate[bot] in
[#9173](#9173)
- update rust crate signal-hook to 0.4 by @renovate[bot] in
[#9177](#9177)
- update rust crate zipsign-api to 0.2 by @renovate[bot] in
[#9180](#9180)
- update rust crate toml_edit to 0.25 by @renovate[bot] in
[#9179](#9179)
- update rust crate strum to 0.28 by @renovate[bot] in
[#9178](#9178)

### 📦 Registry

- add ibmcloud by @dnwe in
[#9139](#9139)
- add rush by @jdx in [#9146](#9146)

### New Contributors

- @80avin made their first contribution in
[#9151](#9151)
- @atharvasingh7007 made their first contribution in
[#9124](#9124)
- @lechuckcaptain made their first contribution in
[#8782](#8782)
- @ergofriend made their first contribution in
[#9102](#9102)
- @dnwe made their first contribution in
[#9139](#9139)

## 📦 Aqua Registry Updates

#### New Packages (3)

-
[`controlplaneio-fluxcd/flux-operator`](https://github.com/controlplaneio-fluxcd/flux-operator)
-
[`dependency-check/DependencyCheck`](https://github.com/dependency-check/DependencyCheck)
- [`kiro.dev/kiro-cli`](https://github.com/kiro.dev/kiro-cli)

#### Updated Packages (2)

-
[`jreleaser/jreleaser/standalone`](https://github.com/jreleaser/jreleaser/standalone)
- [`sigstore/cosign`](https://github.com/sigstore/cosign)
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.

2 participants