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 = """\ ---