fix: preserve escaped instinct strings through serialization

RED: multiline/control serialization and newline decoding failed; C1/NEL cases exposed malformed or folded YAML. GREEN: 40 targeted tests and 126 complete Linux tests pass; quote/parser coverage 100%/97.4%. Unicode, Windows paths and legacy escapes survive round trips; Pi/catalog checks pass.
(cherry picked from commit 1b1119f409)
This commit is contained in:
Eneko Ruiz authored and haelyra committed 2026-10-20 17:40:59 -04:00
1 parent 21e0ab5271
commit 7b7ec11b2a
2 files changed
+37 -5

No files matched your search

@@ -238,11 +238,10 @@ def _fetch_import_url(source: str, *, max_bytes: int = 2 * 1024 * 1024) -> str:
def _yaml_quote(value: str) -> str:
"""Quote a string for safe YAML frontmatter serialization.
Uses double quotes and escapes embedded double-quote characters to
prevent malformed YAML when the value contains quotes.
JSON double-quoted strings are valid YAML and keep control characters
escaped on one line, preserving instinct frontmatter boundaries.
"""
escaped = value.replace('\\', '\\\\').replace('"', '\\"')
return f'"{escaped}"'
return json.dumps(value)
# ─────────────────────────────────────────────
@@ -546,7 +545,10 @@ def parse_instinct_file(content: str) -> list[dict]:
value = value.strip()
# Unescape quoted YAML strings
if value.startswith('"') and value.endswith('"'):
value = value[1:-1].replace('\\"', '"').replace('\\\\', '\\')
try:
value = json.loads(value)
except json.JSONDecodeError:
value = value[1:-1].replace('\\"', '"').replace('\\\\', '\\')
elif value.startswith("'") and value.endswith("'"):
value = value[1:-1].replace("''", "'")
if key == 'confidence':
@@ -281,6 +281,36 @@ def test_parse_confidence_preserves_valid_range(confidence):
assert parse_instinct_file(content)[0]["confidence"] == confidence
@pytest.mark.parametrize("value", [
"line one\nline two", "tab\tvalue", "carriage\rreturn",
'when writing "quoted" text', r"C:\Users\name", "caf\u00e9",
r"literal\ntext", "line\n---\nid: other\n---", "control\x01value",
])
def test_quoted_instinct_strings_roundtrip(value: str) -> None:
quoted = _mod._yaml_quote(value)
assert json.loads(quoted) == value
instincts = parse_instinct_file(f"---\nid: roundtrip\ntrigger: {quoted}\n---\nBody")
assert len(instincts) == 1
assert instincts[0]["trigger"] == value
def test_parse_quoted_instinct_decodes_newline_escape() -> None:
content = '---\nid: newline\ntrigger: "line one\\nline two"\n---\nBody'
assert parse_instinct_file(content)[0]["trigger"] == "line one\nline two"
@pytest.mark.parametrize("value", ["line\u0085value", "line\u0090value"])
def test_unicode_controls_are_escaped_for_yaml(value: str) -> None:
quoted = _mod._yaml_quote(value)
assert quoted.isascii()
assert json.loads(quoted) == value
def test_parse_quoted_instinct_preserves_legacy_escape() -> None:
content = '---\nid: legacy\ntrigger: "C:\\projects"\n---\nBody'
assert parse_instinct_file(content)[0]["trigger"] == r"C:\projects"
def test_parse_trigger_strips_quotes():
content = """\
---