Skip to content

Bug: _resolve_skill only supports folder-shaped {name}/SKILL.md skills for shared sources, not .dmx/skills/ or bundled #40

Description

@hpieris-dm

Problem

_resolve_skill (src/dmx/loop_tools.py) supports two skill shapes — dmx's own flat {name}.md and the folder-shaped {name}/SKILL.md (the agentskills.io / Claude Code ecosystem convention, with optional scripts//references//assets/) — but only for shared sources. The project's own .dmx/skills/ override directory, and the bundled skills directory, only ever look for the flat form:

    candidates = [name, f"dmx-{name}"]

    project_skills = workspace_root / ".dmx" / "skills"
    for candidate in candidates:
        path = project_skills / f"{candidate}.md"
        if path.exists():
            return ResolvedSkill(raw=path.read_text())

    for source in read_shared_sources(workspace_root):
        source_skills = source_root(workspace_root, source) / "skills"
        for candidate in candidates:
            path = source_skills / f"{candidate}.md"
            if path.exists():
                return ResolvedSkill(raw=path.read_text())
        for candidate in candidates:
            skill_dir = source_skills / candidate
            path = skill_dir / "SKILL.md"
            if path.exists():
                return ResolvedSkill(
                    raw=path.read_text(), root_path=str(skill_dir.relative_to(workspace_root))
                )

The .dmx/skills/ block (checked first) has no {name}/SKILL.md fallback at all. Neither does the bundled-skills block further down (bundled.rglob(f"{candidate}.md")).

Net effect: dropping a folder-shaped skill directly into a project's own .dmx/skills/my-skill/SKILL.md does nothing — _resolve_skill won't find it there, falls through to shared sources, then bundled, and returns None if nothing else matches that name. The folder shape only works today if it arrives via a vendored shared source (.dmx/vendor/{source}/skills/{name}/SKILL.md).

This looks like an oversight from GH-27 phase 4, not a deliberate scoping choice — that work added the folder-shape fallback specifically so an org's shared-source repo could be an already-standards-shaped skills repo "with zero dmx-specific restructuring." The same convenience (author a skill once, in the standard shape, and have dmx find it wherever it lives) was never extended to a project's own local skills or to dmx's bundled skills.

Proposal

Extract the flat-then-folder lookup GH-27 phase 4 already wrote for shared sources into a small shared helper (_find_skill_in_dir(skills_dir, candidates) -> ResolvedSkill | None, checking {candidate}.md then {candidate}/SKILL.md for each candidate), and use it for all three tiers:

  1. .dmx/skills/ (project override)
  2. .dmx/vendor/{source}/skills/ (shared sources, already does this)
  3. bundled skills/ (dmx's own)

root_path should be set the same way for any tier's folder-shaped match — it's not specific to shared sources, it's needed any time a skill has its own directory for scripts//references//assets/ to resolve against.

Out of scope

  • Changing catalog.load_skills/_register_skill (MCP slash-command / @app.prompt registration) — that's a separate, larger gap already tracked in Feature: expose shared-source (and app-repo-local) skills as slash commands #35 (shared-source and app-repo-local skills aren't exposed as slash commands at all, regardless of shape). This issue is scoped to the loop runtime's get_skill_definition/_resolve_skill path only.
  • Adding new skill shapes beyond flat and {name}/SKILL.md.

Acceptance criteria

  • A skill at .dmx/skills/{name}/SKILL.md (no .dmx/skills/{name}.md present) resolves via _resolve_skill and get_skill_definition, with root_path set to .dmx/skills/{name}.
  • Same for .dmx/skills/dmx-{name}/SKILL.md.
  • Same for a bundled skill shipped in the folder shape (if/when dmx ships one that way).
  • Existing flat-file resolution at every tier is unaffected — flat still wins over folder-shaped when both exist for the same name (matching the existing shared-source precedence, which checks flat first).
  • Existing shared-source folder-shape behavior (Feature: org-wide shared sources for loops, skills, and validators #27 phase 4) unaffected — same precedence, same root_path semantics.

Context

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions