From ed3d09fabd479f1f76894ed10fb32403d32585f2 Mon Sep 17 00:00:00 2001 From: Magnus Hedemark Date: Fri, 14 Aug 2026 17:44:11 -0400 Subject: [PATCH] fix(test): correct duplicate-catalog name fixtures for case-sensitive fs test_rejects_duplicate_catalog_names failed on case-sensitive CI filesystems (Ubuntu ext4): the flat-layout fixture wrote both duplicate/ and Duplicate/ with frontmatter name: duplicate, so Duplicate/SKILL.md tripped the name-match guard ('name must match directory name "Duplicate"') before the duplicate-catalog check ran, hiding the expected 'duplicate catalog name "duplicate"' error. Local macOS APFS collapsed the two dirs and passed, concealing the defect. Detect filesystem case-sensitivity with a Probe/probe probe. On case-sensitive filesystems write duplicate/ (name: duplicate) and Duplicate/ (name: Duplicate) so both pass the name-match guard and the downcased-name collision fires the duplicate-catalog error. On case-insensitive filesystems the dirs collapse into one, so write the single dir with name: duplicate and assert the generator succeeds. Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com> --- scripts/test-gen-llms-txt.rb | 46 +++++++++++++++++++++++++++--------- 1 file changed, 35 insertions(+), 11 deletions(-) diff --git a/scripts/test-gen-llms-txt.rb b/scripts/test-gen-llms-txt.rb index c8946e5..c63300b 100644 --- a/scripts/test-gen-llms-txt.rb +++ b/scripts/test-gen-llms-txt.rb @@ -125,25 +125,41 @@ class GenLlmsTxtTest < Minitest::Test def test_rejects_duplicate_catalog_names Dir.mktmpdir("gen-llms-txt") do |root| install_generator(root) - skill = <<~YAML - --- - name: duplicate - description: Duplicate fixture. - --- - YAML - write_skill(root, "duplicate", skill) - write_skill(root, "Duplicate", skill) - stdout, stderr, status = run_generator(root, "--write") - if Dir.glob("#{root}/*/SKILL.md").length == 2 + if case_sensitive_fs?(root) # Case-sensitive filesystem: "duplicate" and "Duplicate" are distinct - # directories whose downcased catalog names collide, so the guard fires. + # directories, so the generator processes both. Each fixture must pass + # the name-match guard first (name matches its own directory name), then + # the downcased catalog names collide and the duplicate-catalog guard + # (not the name-match guard) fires. + write_skill(root, "duplicate", <<~YAML) + --- + name: duplicate + description: Duplicate fixture. + --- + YAML + write_skill(root, "Duplicate", <<~YAML) + --- + name: Duplicate + description: Duplicate fixture. + --- + YAML + + _stdout, stderr, status = run_generator(root, "--write") refute status.success? assert_includes stderr, "duplicate catalog name \"duplicate\"" else # Case-insensitive filesystem (e.g. macOS APFS): the two names collapse # into one directory, so the generator emits a single entry and must not # report a spurious duplicate. + write_skill(root, "duplicate", <<~YAML) + --- + name: duplicate + description: Duplicate fixture. + --- + YAML + + stdout, stderr, status = run_generator(root, "--write") assert status.success?, stderr assert_includes stdout, "Wrote llms.txt (1 skills)." end @@ -152,6 +168,14 @@ class GenLlmsTxtTest < Minitest::Test private + # True when the filesystem under `root` distinguishes case in directory names. + # macOS APFS (case-insensitive) collapses "Probe"/"probe"; Ubuntu ext4 + # (case-sensitive) keeps them distinct. + def case_sensitive_fs?(root) + FileUtils.mkdir_p(File.join(root, "Probe")) + !Dir.exist?(File.join(root, "probe")) + end + def install_generator(root) FileUtils.mkdir_p(File.join(root, "scripts")) FileUtils.cp(GENERATOR, File.join(root, "scripts", "gen-llms-txt.rb"))