Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion harness_manager/upgrade.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ def _new_loop_assets(src_agent: Path, dst_agent: Path) -> list[tuple[Path, Path]
if not skill_dir.is_dir() or (dst_skills / skill_dir.name).exists():
continue
for src in sorted(p for p in skill_dir.rglob("*") if p.is_file()):
actions.append((src, dst_skills / src.relative_to(src_agent)))
actions.append((src, dst_agent / src.relative_to(src_agent)))
return actions


Expand Down
15 changes: 15 additions & 0 deletions tests/test_loop_integrations.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,21 @@ def test_upgrade_adds_missing_loop_assets_but_preserves_authored_contract(tmp_pa
assert (target / ".agent" / "runtime" / ".gitignore").exists()


def test_upgrade_copies_missing_loop_skills_to_the_correct_path(tmp_path: Path):
"""A genuinely-missing loop-* skill must land at .agent/skills/loop-x/,
not .agent/skills/skills/loop-x/ (a doubled path segment regression:
the existing coverage above only ever pre-seeds loop-triage, so it
exercises the "already exists, skip" branch and never the fresh-copy
branch that builds the destination path).
"""
target = make_installed_project(tmp_path)
assert upgrade(target, ROOT, yes=True) == 0
for name in ("loop-constraints", "loop-guard", "loop-triage", "loop-verifier"):
dst = target / ".agent" / "skills" / name / "SKILL.md"
assert dst.is_file(), f"expected {dst}, not doubled under skills/skills/"
assert not (target / ".agent" / "skills" / "skills").exists()


def test_upgrade_does_not_copy_runtime_children_or_overwrite_loop_skills(tmp_path: Path):
target = make_installed_project(tmp_path)
skill = target / ".agent" / "skills" / "loop-triage"
Expand Down