Skip to content

Commit 9ffaa4d

Browse files
alpha-86claude
andcommitted
fix: bootstrap-sync replace order bug causing adf-.claude path errors
- bootstrap-sync: use negative lookbehind to prevent substring replacement - bootstrap-sync: reverse replacement order (full path first, then short pattern) - start-agent-team: clarify Team Lead is Claude Code window itself Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 201972f commit 9ffaa4d

2 files changed

Lines changed: 17 additions & 16 deletions

File tree

.github/workflows/bootstrap-sync.py

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -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

skills/start-agent-team/SKILL.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,10 @@
3030

3131
- 确认当前项目标识 `project_id`
3232
- 确认当前主 issue 或主工作索引
33-
- 确认 团队负责人
3433
- 确认本轮需要启用的角色
3534

35+
> ****:Team Lead(团队负责人)是当前 Claude Code 窗口本身(Human),是 Agent Team 系统的保留角色,无需确认或创建。
36+
3637
### 步骤 0.5. Team 创建检查
3738

3839
> ****:每次执行 start-agent-team 时,**必须假设团队不存在**,从零开始检查和创建。上一个 session 的任何配置文件、日志、状态记录都与当前 session 无关。

0 commit comments

Comments
 (0)