Skip to content

Commit 104db76

Browse files
tbitcsoz-agent
andcommitted
fix: auto-update AGENTS.md references when migrating lowercase→uppercase filenames
When upgrade renames governance files (rules.md→RULES.md etc.), it now also rewrites path references in AGENTS.md, CLAUDE.md, GEMINI.md, SKILL.md, .cursor/rules/, .windsurfrules, and .aider.conf.yml. Eliminates the need for manual reference fixup after upgrade. Co-Authored-By: Oz <oz-agent@warp.dev>
1 parent a9c8251 commit 104db76

1 file changed

Lines changed: 41 additions & 0 deletions

File tree

src/specsmith/upgrader.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,9 +255,13 @@ def _migrate_legacy_filenames(root: Path, result: UpgradeResult) -> None:
255255
Handles both case-sensitive (Linux) and case-insensitive (Windows/macOS)
256256
filesystems. On case-insensitive FS, uses a two-step rename via a
257257
temporary name to avoid conflicts.
258+
259+
Also updates references in AGENTS.md so the hub links stay valid.
258260
"""
259261
import shutil
260262

263+
renamed: list[tuple[str, str]] = []
264+
261265
for old_rel, new_rel in _LEGACY_RENAMES:
262266
old_path = root / old_rel
263267
new_path = root / new_rel
@@ -276,4 +280,41 @@ def _migrate_legacy_filenames(root: Path, result: UpgradeResult) -> None:
276280
shutil.move(str(old_path), str(new_path))
277281
else:
278282
continue # Both exist as truly separate files — skip
283+
renamed.append((old_rel, new_rel))
279284
result.updated_files.append(f"{old_rel}{new_rel}")
285+
286+
# Update references in user-owned docs that point to renamed files
287+
if renamed:
288+
_update_references(root, renamed, result)
289+
290+
291+
def _update_references(
292+
root: Path,
293+
renames: list[tuple[str, str]],
294+
result: UpgradeResult,
295+
) -> None:
296+
"""Rewrite old paths to new paths in AGENTS.md and other hub files.
297+
298+
Only performs safe string replacement of exact path references.
299+
"""
300+
docs_to_patch = [
301+
"AGENTS.md",
302+
"CLAUDE.md",
303+
"GEMINI.md",
304+
".warp/skills/SKILL.md",
305+
".cursor/rules/governance.mdc",
306+
".windsurfrules",
307+
".aider.conf.yml",
308+
]
309+
310+
for doc_name in docs_to_patch:
311+
doc_path = root / doc_name
312+
if not doc_path.exists():
313+
continue
314+
content = doc_path.read_text(encoding="utf-8")
315+
original = content
316+
for old_rel, new_rel in renames:
317+
content = content.replace(old_rel, new_rel)
318+
if content != original:
319+
doc_path.write_text(content, encoding="utf-8")
320+
result.updated_files.append(f"{doc_name} (references updated)")

0 commit comments

Comments
 (0)