Skip to content

fix(modify): quote --set-field values so a colon-space no longer corrupts the file (#687)#691

Open
avrabe wants to merge 1 commit into
mainfrom
fix/issue-687-set-field-yaml-quoting
Open

fix(modify): quote --set-field values so a colon-space no longer corrupts the file (#687)#691
avrabe wants to merge 1 commit into
mainfrom
fix/issue-687-set-field-yaml-quoting

Conversation

@avrabe

@avrabe avrabe commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

Closes #687.

Bug

rivet modify --set-field key=value used to write the value RAW under a
block-style fields: sub-map — every sibling setter (--set-title,
--set-status, --set-release, --set-description) already routes
through yaml_quote_inline_scalar, but the set_fields loop skipped it.
A value containing : (or any other plain-scalar indicator — #,
leading -/?/[/{, YAML booleans, …) then produced invalid YAML:

      rationale: CURVE-AGILE: Ed25519 preferred, ECDSA-P256 fallback

The second : reads as a mapping value → parse error on the whole
source file → rivet WARN-and-skips the file → every artifact in it
silently vanishes from the loaded store. Same data-loss shape as
#573/#613/#618 (invalid YAML from a mutation drops the file), just via
the one setter that never got the quoting treatment.

Fix

Route each set_fields value through the existing yaml_quote_inline_scalar
helper before formatting — the fix the issue asked for, one line. Applied at
all three block-style write sites (replace-existing sub-key, insert new sub-key,
create new fields: section). The flow-style branch already went through
serde_yaml, which quotes correctly — left alone.

Acceptance criteria (from the issue's "Suggested fix")

  • Route set_field's value through yaml_quote_inline_scalar.
    Applied at all three block-style write sites in
    rivet-core/src/yaml_edit.rs.
  • (Deferred, not implemented here) Fail loud on parse error during
    validate/get/list. The issue explicitly framed this as "Separately,
    consider" — decoupling it keeps this PR to a single-file bug fix; the
    silent-skip behavior is orthogonal and warrants its own design/PR (it
    affects the error UX of several commands, not just the mutation path).

Verification

  • Three new regression tests (all pass):
    • set_field_quotes_value_with_colon_space_and_preserves_siblings
      insert branch (existing fields:, new sub-key), sibling artifact survives.
    • set_field_creating_fields_section_quotes_hostile_value — create-fields
      branch (no pre-existing fields:).
    • set_field_updating_existing_key_quotes_hostile_value — replace branch
      (existing sub-key overwritten).
  • All 38 yaml_edit tests pass; nothing else in the module was touched.
  • End-to-end reproduction of the exact issue command:
    $ rivet modify DD-1 --set-field 'rationale=CURVE-AGILE: Ed25519 preferred, ECDSA-P256 fallback'
    modified DD-1
    $ rivet get DD-1     # succeeds; rationale round-trips verbatim
    $ rivet get DD-2     # sibling artifact survives (used to vanish)
    
    File now contains:
          rationale: "CURVE-AGILE: Ed25519 preferred, ECDSA-P256 fallback"
  • CI gates green locally: cargo fmt --all -- --check, cargo clippy --all-targets -- -D warnings, rivet validate (PASS).

Generated by Claude Code

…upts the file (#687)

`rivet modify --set-field key=value` used to write the value RAW under a
block-style `fields:` sub-map — every sibling setter (`--set-title`,
`--set-status`, `--set-release`, `--set-description`) already routes
through `yaml_quote_inline_scalar`, but the `set_fields` loop skipped it.
A value containing `: ` (or any other plain-scalar indicator — `#`,
leading `-`/`?`/`[`/`{`, YAML booleans, …) then produced invalid YAML:

    rationale: CURVE-AGILE: Ed25519 preferred, ECDSA-P256 fallback ...

The second `: ` reads as a mapping value → parse error on the whole
source file → rivet WARN-and-skips the file → every artifact in it
silently vanishes from the loaded store. Same data-loss shape as
#573/#613/#618 (invalid YAML from a mutation drops the file), just via
the one setter that never got the quoting treatment.

Fix: route each `set_fields` value through the existing
`yaml_quote_inline_scalar` helper before formatting. Applied at all three
block-style write sites (replace-existing sub-key, insert new sub-key,
create new `fields:` section). The flow-style branch already went through
`serde_yaml`, which quotes correctly — left alone.

Confirmed end-to-end: `rivet modify DD-1 --set-field
'rationale=CURVE-AGILE: Ed25519 preferred'` now writes
`rationale: "CURVE-AGILE: Ed25519 preferred"`, the file stays parseable,
both artifacts round-trip through `rivet get`, and the hostile value
survives verbatim. Three regression tests cover the insert branch, the
create-fields-section branch, and the replace-existing branch.

Fixes: REQ-034
Verifies: REQ-034
@codecov

codecov Bot commented Jul 11, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@github-actions

Copy link
Copy Markdown

📐 Rivet artifact delta

No artifact changes in this PR. Code-only changes (renderer, CLI wiring, tests) don't touch the artifact graph.

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.

rivet modify --set-field writes colon-space (and other) values UNQUOTED → invalid YAML → whole file silently skipped

2 participants