@@ -105,38 +105,38 @@ def replace_internal_references(content: str, mapping: dict[str, str]) -> str:
105105 """Replace all internal skill references in content.
106106
107107 Patterns replaced:
108- - /{orig} → /adf-{adf} (skill invocation paths)
108+ - /{orig} → /adf-{adf} (skill invocation paths, uses negative lookbehind to avoid substring matches )
109109 - Skill("{orig}") → Skill("{adf}") (skill invocation calls)
110- - {orig}/SKILL.md → .claude/skills/{adf}/SKILL.md (skill file references)
110+ - {orig}/SKILL.md → .claude/skills/{adf}/SKILL.md (skill file references, uses negative lookbehind )
111111 - skills/{orig}/SKILL.md → .claude/skills/{adf}/SKILL.md (skills prefix references)
112112 """
113113
114114 # Only apply replacements for non-skipped items
115115 skip_set = {* SKIP_FILES }
116116
117- replacements = []
117+ # Use regex with negative lookbehind to avoid substring matches
118+ # e.g., team-setup must not match inside adf-team-setup
119+ import re as re_module
118120
119121 for orig , adf in mapping .items ():
120122 if orig in skip_set :
121123 continue
122124
123125 # Skill invocation paths: /agent-bootstrap → /adf-agent-bootstrap
124- replacements .append ((f"/{ orig } " , f"/{ adf } " ))
126+ # Use negative lookbehind with / excluded to avoid matching /team-setup inside paths
127+ content = re_module .sub (rf'(?<![\w/])/{ re_module .escape (orig )} (?![\w/])' , f'/{ adf } ' , content )
125128
126129 # Skill invocation calls: Skill("product-manager") → Skill("adf-product-manager")
127- replacements . append (( f'Skill("{ orig } ")' , f'Skill("{ adf } ")' ) )
130+ content = content . replace ( f'Skill("{ orig } ")' , f'Skill("{ adf } ")' )
128131
129- # Subdirectory references: product-manager/SKILL.md → .claude/skills/adf-product-manager/SKILL.md
130- replacements .append ((f"{ orig } /SKILL.md" , f".claude/skills/{ adf } /SKILL.md" ))
132+ # FIRST: full path with skills/ prefix — must be done before the short pattern
133+ # to avoid matching team-setup inside skills/team-setup/SKILL.md
134+ content = content .replace (f"skills/{ orig } /SKILL.md" , f".claude/skills/{ adf } /SKILL.md" )
131135
132- # Also handle skills/ prefix: skills/architect/SKILL.md → .claude/skills/adf-architect/SKILL.md
133- replacements .append ((f"skills/{ orig } /SKILL.md" , f".claude/skills/{ adf } /SKILL.md" ))
134-
135- # Sort by length descending to avoid partial replacement issues
136- replacements .sort (key = lambda x : - len (x [0 ]))
137-
138- for old , new in replacements :
139- content = content .replace (old , new )
136+ # SECOND: short pattern without skills/ prefix — only matches standalone {orig}/SKILL.md
137+ # Use negative lookbehind (?<![\w-/]) to prevent matching team-setup inside
138+ # skills/team-setup/SKILL.md or adf-team-setup/SKILL.md
139+ content = re_module .sub (rf'(?<![\w\-/]){ re_module .escape (orig )} /SKILL\.md\b' , f'.claude/skills/{ adf } /SKILL.md' , content )
140140
141141 return content
142142
0 commit comments