Repository: code-yeongyu/oh-my-openagent (2026-04-02T01:40:24Z)

Issue:
[Bug]: Skill short names are exposed but not resolvable by the skill resolver
## Prerequisites
- [x] I will write this issue in English (see the Language Policy)
- [x] I have searched existing issues to avoid duplicates
- [x] I am using the latest version of oh-my-opencode
- [x] I have read the documentation or asked an AI coding agent with this project's GitHub URL loaded and couldn't find the answer

## Bug Description
In an OpenCode environment with oh-my-opencode installed, some superpowers skills are surfaced to the user by their short names (for example `systematic-debugging`), but the `skill` resolver does not actually accept those short names.

Calling the visible short name fails with a `not found` error, and the error message then suggests using the fully qualified name such as `superpowers/systematic-debugging` or the slash-command form `/superpowers:systematic-debugging`.

From a user perspective, this looks like a product bug rather than user error, because the visible skill name is not the same as the executable identifier.

## Steps to Reproduce
1. In the current environment, invoke the skill using the visible short name:
   ```text
   systematic-debugging
   ```
   or call the skill resolver/tool with that same short name.
2. Observe the error:
   ```text
   Skill or command "systematic-debugging" not found. Did you mean: superpowers/systematic-debugging, /superpowers:systematic-debugging?
   ```
3. Retry with the fully qualified name:
   ```text
   superpowers/systematic-debugging
   ```
4. The invocation succeeds.

## Expected Behavior
If a skill is exposed in the available-skills list / UI / context as `systematic-debugging`, that short name should be directly resolvable by the `skill` mechanism.

If short names are intentionally unsupported, then the system should consistently expose only the fully qualified name, so users are not guided toward an invalid invocation.

## Actual Behavior
- The skill is surfaced to the user as a short name like `systematic-debugging`
- The resolver rejects that short name
- The resolver only accepts the fully qualified form such as `superpowers/systematic-debugging`
- The error message teaches the workaround only after the failure happens

## Doctor Output
```shell
$ bunx oh-my-opencode doctor

 oMoMoMoMo Doctor 

 ⚠ 3 issues found:

1. Model override uses unavailable provider
   Provider(s) not found in OpenCode model cache: axonhub, Custom:Nvidia Nim
   Affects: model resolution

2. Comment checker unavailable
   Comment checker binary is not installed.
   Fix: Install @code-yeongyu/comment-checker
   Affects: comment-checker hook

3. Configured models rely on compatibility fallback
   multimodal-looker=google/antigravity-gemini-3-flash (heuristic-backed)
   Affects: multimodal-looker
```

## Error Logs
```shell
Skill or command "systematic-debugging" not found. Did you mean: superpowers/systematic-debugging, /superpowers:systematic-debugging?
```

## Configuration
```json
{
  "note": "No minimal config snippet isolated yet. The issue appears to be in skill name exposure vs resolver namespace handling rather than a user-specific config mistake."
}
```

## Additional Context
My current guess is that the short-name alias is being displayed but not registered in the runtime resolver, or that the resolver is not expanding short names back to the canonical `superpowers/...` identifier.

In other words, the presentation layer and the execution layer seem to disagree about the valid skill identifier.

Current workaround:
- `superpowers/systematic-debugging`
- `/superpowers:systematic-debugging`

## Operating System
macOS

## OpenCode Version
1.3.9



Discussion:
<img width="2016" height="304" alt="Image" src="https://github.com/user-attachments/assets/87b4f04d-f9ea-4761-9f7c-8942b261c61b" />



Patch:
diff --git a/src/tools/skill/tools.ts b/src/tools/skill/tools.ts
index 70d2016e3f..68ac1a827d 100644
--- a/src/tools/skill/tools.ts
+++ b/src/tools/skill/tools.ts
@@ -324,7 +324,19 @@ export function createSkillTool(options: SkillLoadOptions = {}): ToolDefinition
       const requestedName = args.name.replace(/^\//, "")
 
       // Check skills first (exact match, case-insensitive)
-      const matchedSkill = skills.find(s => s.name.toLowerCase() === requestedName.toLowerCase())
+      let matchedSkill = skills.find(s => s.name.toLowerCase() === requestedName.toLowerCase())
+
+      // Fallback: try matching by short name (basename) for namespaced skills
+      // e.g. "systematic-debugging" matches "superpowers/systematic-debugging"
+      if (!matchedSkill) {
+        const shortNameMatches = skills.filter(s => {
+          const parts = s.name.split("/")
+          return parts.length > 1 && parts[parts.length - 1].toLowerCase() === requestedName.toLowerCase()
+        })
+        if (shortNameMatches.length === 1) {
+          matchedSkill = shortNameMatches[0]
+        }
+      }
 
       if (matchedSkill) {
         if (matchedSkill.definition.agent && (!ctx?.agent || matchedSkill.definition.agent !== ctx.agent)) {


Test patch:
diff --git a/src/tools/skill/tools.test.ts b/src/tools/skill/tools.test.ts
index b5551d1517..5c7282766c 100644
--- a/src/tools/skill/tools.test.ts
+++ b/src/tools/skill/tools.test.ts
@@ -670,3 +670,58 @@ describe("skill tool - nativeSkills integration", () => {
     expect(result).toContain("External plugin skill body")
   })
 })
+
+describe("skill tool - short name resolution", () => {
+  it("resolves namespaced skill by short name when unambiguous", async () => {
+    // given
+    const loadedSkills = [createMockSkill("superpowers/systematic-debugging")]
+    const tool = createSkillTool({ skills: loadedSkills })
+
+    // when
+    const result = await tool.execute({ name: "systematic-debugging" }, mockContext)
+
+    // then
+    expect(result).toContain("superpowers/systematic-debugging")
+  })
+
+  it("still resolves by exact full name", async () => {
+    // given
+    const loadedSkills = [createMockSkill("superpowers/systematic-debugging")]
+    const tool = createSkillTool({ skills: loadedSkills })
+
+    // when
+    const result = await tool.execute({ name: "superpowers/systematic-debugging" }, mockContext)
+
+    // then
+    expect(result).toContain("superpowers/systematic-debugging")
+  })
+
+  it("does not resolve short name when ambiguous (multiple matches)", async () => {
+    // given
+    const loadedSkills = [
+      createMockSkill("superpowers/debugging"),
+      createMockSkill("utils/debugging"),
+    ]
+    const tool = createSkillTool({ skills: loadedSkills })
+
+    // when / then — should not resolve (ambiguous), should suggest both
+    await expect(tool.execute({ name: "debugging" }, mockContext)).rejects.toThrow(
+      "not found"
+    )
+  })
+
+  it("prefers exact match over short name match", async () => {
+    // given — "debugging" exists as both exact and as part of a namespace
+    const loadedSkills = [
+      createMockSkill("debugging"),
+      createMockSkill("superpowers/debugging"),
+    ]
+    const tool = createSkillTool({ skills: loadedSkills })
+
+    // when
+    const result = await tool.execute({ name: "debugging" }, mockContext)
+
+    // then — should match "debugging" exactly, not "superpowers/debugging"
+    expect(result).toContain("## Skill: debugging")
+  })
+})