From 60ce177d748434b1bdb95d5c908f25cad9cf8bb2 Mon Sep 17 00:00:00 2001 From: Eneko Ruiz <196690101+eneekoruiz@users.noreply.github.com> Date: Sun, 11 Oct 2026 11:33:47 +0200 Subject: [PATCH] fix: accept a leading UTF-8 BOM in instinct files RED: BOM parsing and disk loading failed in 3 cases. GREEN: 18 targeted tests pass, including LF/CRLF and preserving interior BOM characters. parse_instinct_file line coverage is 91.4%. --- .../scripts/instinct-cli.py | 2 +- .../scripts/test_parse_instinct.py | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/skills/continuous-learning-v2/scripts/instinct-cli.py b/skills/continuous-learning-v2/scripts/instinct-cli.py index f7f35abbb..8977f5f6c 100755 --- a/skills/continuous-learning-v2/scripts/instinct-cli.py +++ b/skills/continuous-learning-v2/scripts/instinct-cli.py @@ -525,7 +525,7 @@ def parse_instinct_file(content: str) -> list[dict]: in_frontmatter = False content_lines = [] - for line in content.split('\n'): + for line in content.removeprefix('\ufeff').split('\n'): if line.strip() == '---': if in_frontmatter: # End of frontmatter - content comes next diff --git a/skills/continuous-learning-v2/scripts/test_parse_instinct.py b/skills/continuous-learning-v2/scripts/test_parse_instinct.py index f58c58853..6dd7307f6 100644 --- a/skills/continuous-learning-v2/scripts/test_parse_instinct.py +++ b/skills/continuous-learning-v2/scripts/test_parse_instinct.py @@ -208,6 +208,23 @@ Prevents vulnerabilities. assert "Prevents vulnerabilities." in result[0]["content"] +@pytest.mark.parametrize("newline", ["\n", "\r\n"]) +def test_parse_initial_utf8_bom(newline): + content = SAMPLE_INSTINCT_YAML.replace("\n", newline) + assert parse_instinct_file("\ufeff" + content) == parse_instinct_file(content) + + +def test_parse_preserves_bom_inside_content(): + content = SAMPLE_INSTINCT_YAML.replace("Always write", "Always \ufeffwrite") + assert "Always \ufeffwrite" in parse_instinct_file(content)[0]["content"] + + +def test_load_instinct_file_with_utf8_bom(tmp_path): + (tmp_path / "bom.yaml").write_text(SAMPLE_INSTINCT_YAML, encoding="utf-8-sig") + instincts = _load_instincts_from_dir(tmp_path, "personal", "project") + assert [instinct["id"] for instinct in instincts] == ["test-instinct"] + + def test_empty_content_no_error(): content = """\ ---