Skip to content

fix(kyaml): escape U+2028 and U+2029 so keys stay parseable by yq - #250

Merged
hyperpolymath merged 1 commit into
mainfrom
claude/gallant-bell-4bo4oy-g-kyaml-line-separators
Oct 26, 2026
Merged

hyperpolymath merged 1 commit into
mainfrom
claude/gallant-bell-4bo4oy-g-kyaml-line-separators

Conversation

@hyperpolymath

Copy link
Copy Markdown
Owner

Follow-up to #248 (KYAML report output), found while drafting the upstream yq issue about its KYAML encoder.

Problem

go-yaml, the parser behind yq and standards' scripts/kyaml-format.sh, treats a raw U+2028 (LS) or U+2029 (PS) as a line break, which is YAML 1.1 behaviour. Our emitter already escaped NEL (U+0085) but wrote LS and PS raw. A report key holding either one therefore produced KYAML that yq could not read at all:

$ yq -p yaml -o json old.kyaml      # key "x<LS>y" written raw
Error: ... go-yaml load error in parser (while parsing a flow mapping) ... did not find expected ',' or '}'

Values were unaffected, and crate::yaml (serde-saphyr, YAML 1.2) read these files correctly before and after. In #248 I deliberately left U+2028 raw because YAML 1.2 calls it printable. Testing keys showed that was the wrong call for interop.

Fix

write_quoted also escapes U+2028 and U+2029 as and . Those escapes are valid in YAML 1.1 and 1.2, so nothing that parsed the old output loses anything.

Validation

  • cargo fmt --check, plus cargo clippy --all-targets -D warnings with and without --all-features: clean.
  • cargo test --all-features: all suites green (lib: 510 passed).
  • New test line_breaks_in_keys_are_escaped covers NEL, LS and PS in keys: exact output, and a round trip through crate::yaml. Run against the previous escape set, it fails with the raw separator in the output ("x\u{2028}y").
  • escapes_non_printables_that_yq_writes_raw is updated: it asserted LS stays raw, and now asserts it is escaped.
  • End to end with real yq v4.54.1: KYAML from this branch with NEL, LS or PS in a key reads back intact (yq -p yaml -o json).

One thing this PR can't fix

kyaml-format.sh --check still refuses these files: REFUSED — the KYAML rendering does not parse to the same data. The gate re-renders through yq -o kyaml, and yq's encoder writes the characters raw again. That is the upstream yq bug:

  • With a yq built from my proposed upstream patch, the same three files pass (all 3 file(s) are KYAML).
  • The upstream issue is drafted but not filed yet; filing it is the owner's call.

Until yq is fixed, a report key containing NEL, LS or PS can't pass the gate. Such keys are rare in practice, since report keys are field names and file paths.


Generated by Claude Code

go-yaml, the parser behind yq and standards' kyaml-format.sh, reads a
raw LS or PS as a line break (YAML 1.1 behaviour). In a key that makes
the document unparseable: `{"x<LS>y": 1}` written by `--output-format
kyaml` failed with "did not find expected ',' or '}'". NEL was already
escaped; LS and PS now are too, as `
` / `
`, which is valid
in YAML 1.1 and 1.2. serde-saphyr read the files correctly either way.

A new test covers NEL, LS and PS in keys; it fails on the previous
escape set with the raw separator in the output.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PFaqv6iBXrt3W5Akd1Fq5k
@coderabbitai

coderabbitai Bot commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review.

Recent review info
Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: 0db06f17-4a51-4ce2-9ea6-da493a5aad50
Commits

Reviewing files that changed from the base of the PR and between 2285a77 and e914d7c.

Files selected for processing: 2
  • CHANGELOG.adoc
  • src/kyaml.rs

Included review availability: This review used your included allowance. Your plan provides up to 1 included review per hour; 0 remain after this review.

Recent review details
Context from checks skipped due to timeout: 23
  • GitHub Check: chapel-ci-gate
  • GitHub Check: Validate DEED manifests
  • GitHub Check: Validate K9 contracts
  • GitHub Check: scan / rust-secrets
  • GitHub Check: scan / gitleaks
  • GitHub Check: scan / shell-secrets
  • GitHub Check: Line coverage (cargo-llvm-cov)
  • GitHub Check: E2E — VeriSimDB Integration
  • GitHub Check: E2E — Full Scan Pipeline
  • GitHub Check: Readiness — Component Grade Verification
  • GitHub Check: cargo fmt --check
  • GitHub Check: cargo test (http,sarif)
  • GitHub Check: CI integrity (pins, lock, allowlist, YAML)
  • GitHub Check: Coverage ledger is honest (--fail-on-incomplete)
  • GitHub Check: cargo doc (no broken intra-doc links)
  • GitHub Check: MSRV (rust-version in Cargo.toml)
  • GitHub Check: cargo test ()
  • GitHub Check: Bench — Scan Performance
  • GitHub Check: Ledger — coverage derived from executed tests
  • GitHub Check: analyze (actions, none)
  • GitHub Check: cargo clippy -D warnings
  • GitHub Check: Cargo Audit
  • GitHub Check: semgrep-cloud-platform/scan
Additional comments: 2
src/kyaml.rs: 1

19-25: LGTM!

Also applies to: 109-114, 158-158, 162-162, 169-182

CHANGELOG.adoc: 1

5-12: LGTM!

📝 Summary

Summary by CodeRabbit

  • Bug Fixes
    • KYAML output now escapes U+2028 and U+2029, preventing these characters from being misread as line breaks in keys.
    • Values and keys containing these characters can be written and read back successfully.

KYAML now escapes U+2028 and U+2029 in quoted output. Documentation and tests cover these characters alongside NEL, including parsing keys that contain the separators.

Changes: KYAML separator escaping

Layer / File(s) Summary
Escape and validate Unicode separators
src/kyaml.rs, CHANGELOG.adoc
write_quoted escapes U+2028 and U+2029. The documentation and changelog describe the escape behaviour and parser handling. Tests cover value escaping and verify that keys containing NEL, U+2028 or U+2029 parse back to the original value.

Priority: Normal

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix

Possibly related PRs

Suggested reviewers: metadatastician

Merge Risk: Minimal · up to e914d

The change is mergeable with no identified current-head risk.

Pre-merge checks: Passed 4 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 4 functions across 1 files. (1 skipped: 1 … Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 4 passed
Check name Status Explanation
Title check Passed The title clearly and concisely identifies the main change: escaping U+2028 and U+2029 in KYAML so keys remain parseable by yq.
Description check Passed The description directly explains the parsing problem, the KYAML fix, the tests, validation results, and the remaining yq limitation.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 4 functions across 1 files. (1 skipped: 1 unsupported.)

Resolution

Write docstrings for the functions missing them to satisfy the coverage threshold.

Finishing Touches: 💡 1
📝 Generate docstrings: 💡
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@linear-code
linear-code Bot marked this pull request as ready for review October 26, 2026 22:15
@hyperpolymath
hyperpolymath merged commit ac68bba into main Oct 26, 2026
40 checks passed
@hyperpolymath
hyperpolymath deleted the claude/gallant-bell-4bo4oy-g-kyaml-line-separators branch October 26, 2026 22:28
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