Skip to content

fix: numeric skill names, ZWSP agent lookups, ultrawork run_in_background - #3436

Merged
code-yeongyu merged 1 commit into
devfrom
fix/bug-batch-1
Apr 15, 2026
Merged

code-yeongyu merged 1 commit into
devfrom
fix/bug-batch-1

Conversation

@code-yeongyu

@code-yeongyu code-yeongyu commented Apr 15, 2026 •

Copy link
Copy Markdown
Owner

Bug Fixes

#3354: Numeric skill name crashes ALL slash commands

  • Added String() coercion in loadSkillFromPath() and loadSkillFromPathAsync()
  • When YAML frontmatter has name: 12306, js-yaml parses as number, causing cmd.name.toLowerCase() crash

#3379 / #3417 / #3418 / #3337 / #3335: ZWSP prefix breaks agent name lookups

  • Added stripInvisibleAgentCharacters() calls across 8 files:
    • agent-tool-restrictions.ts - agent restriction lookup
    • sync-prompt-sender.ts - oracle agent detection
    • tool-execute-after.ts - verification context check
    • tool-execute-before.ts - subagent type normalization
    • oracle-verification-detector.ts - oracle agent matching
    • call-omo-agent/tools.ts - agent validation
    • recovery-prompt-config.ts - agent comparison
    • agent-variant.ts - variant resolution
  • Also improved resolveKnownAgentConfigKey() to handle parenthetical suffixes

#3416: ultrawork prompts missing run_in_background

  • Added run_in_background: true/false to all task() examples in:
    • ultrawork/default.ts
    • ultrawork/gemini.ts
    • ultrawork/gpt.ts
    • ultrawork/planner.ts

Already fixed in dev (verified):

Verification: bun tsc --noEmit clean, 5451 tests passing (0 failures)

Closes #3354, closes #3379, closes #3417, closes #3418, closes #3337, closes #3335, closes #3416


Summary by cubic

Fixes crashes from numeric skill names, makes agent name lookups robust to zero‑width spaces, and updates ultrawork task() examples to include the required run_in_background flag. This prevents command failures, ensures correct agent resolution, and aligns examples with the tool schema.

  • Bug Fixes
    • Coerce skill name to String in loadSkillFromPath() and loadSkillFromPathAsync() to handle YAML numeric names.
    • Strip zero‑width/invisible characters from agent names before comparisons across restrictions, session prompts, oracle verification, call_omo_agent, recovery prompts, and variant resolution.
    • Add explicit run_in_background to all ultrawork task() examples (default, gpt, gemini, planner) to match the schema and clarify foreground vs background runs.

Written for commit 62c60ae. Summary will update on new commits.

…gent lookups

- #3354: Coerce data.name to String in loadSkillFromPath/loadSkillFromPathAsync
  to prevent crash when YAML parses numeric skill names (e.g., name: 12306)

- #3416: Add required run_in_background parameter to all task() examples in
  ultrawork prompts (default, gpt, gemini, planner) to match tool schema

- #3379/#3417/#3418/#3337/#3335: Strip ZWSP (U+200B) before agent name
  comparisons in agent-tool-restrictions, sync-prompt-sender, tool-execute-after,
  tool-execute-before, oracle-verification-detector, call-omo-agent,
  recovery-prompt-config, and agent-variant to prevent ZWSP-prefixed display
  names from breaking exact-match lookups

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 14 files

Confidence score: 4/5

  • This PR looks generally safe to merge, with moderate confidence: both findings are medium severity (5/10) and limited to falsy numeric name handling rather than broad runtime stability issues.
  • The most impactful issue is in src/features/opencode-skill-loader/async-loader.ts, where || before coercion causes a valid numeric skill name like 0 to be replaced by defaultName, which can mislabel user-defined skills.
  • A similar edge-case regression exists in src/features/opencode-skill-loader/loaded-skill-from-path.ts, where frontmatter name: 0 is dropped for defaultName due to the same ||-before-String() pattern.
  • Pay close attention to src/features/opencode-skill-loader/async-loader.ts, src/features/opencode-skill-loader/loaded-skill-from-path.ts - preserve falsy numeric names by coercing before fallback logic.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="src/features/opencode-skill-loader/async-loader.ts">

<violation number="1" location="src/features/opencode-skill-loader/async-loader.ts:90">
P2: Falsy numeric skill names (e.g. `0`) still fall back to `defaultName` because the `||` check happens before string coercion.</violation>
</file>

<file name="src/features/opencode-skill-loader/loaded-skill-from-path.ts">

<violation number="1" location="src/features/opencode-skill-loader/loaded-skill-from-path.ts:28">
P2: Falsy frontmatter names are still dropped because `||` runs before `String()`, so `name: 0` falls back to `defaultName` instead of being preserved as "0".</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

const mcpConfig = mcpJsonMcp || frontmatterMcp

const baseName = data.name || defaultName
const baseName = String(data.name || defaultName)

@cubic-dev-ai cubic-dev-ai Bot Apr 15, 2026 •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Falsy numeric skill names (e.g. 0) still fall back to defaultName because the || check happens before string coercion.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/features/opencode-skill-loader/async-loader.ts, line 90:

<comment>Falsy numeric skill names (e.g. `0`) still fall back to `defaultName` because the `||` check happens before string coercion.</comment>

<file context>
@@ -87,7 +87,7 @@ export async function loadSkillFromPathAsync(
     const mcpConfig = mcpJsonMcp || frontmatterMcp
 
-    const baseName = data.name || defaultName
+    const baseName = String(data.name || defaultName)
     const skillName = namePrefix ? `${namePrefix}/${baseName}` : baseName
     const originalDescription = data.description || ""
</file context>
Fix with Cubic

const mcpConfig = mcpJsonMcp || frontmatterMcp

const baseName = data.name || options.defaultName
const baseName = String(data.name || options.defaultName)

@cubic-dev-ai cubic-dev-ai Bot Apr 15, 2026 •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Falsy frontmatter names are still dropped because || runs before String(), so name: 0 falls back to defaultName instead of being preserved as "0".

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At src/features/opencode-skill-loader/loaded-skill-from-path.ts, line 28:

<comment>Falsy frontmatter names are still dropped because `||` runs before `String()`, so `name: 0` falls back to `defaultName` instead of being preserved as "0".</comment>

<file context>
@@ -25,7 +25,7 @@ export async function loadSkillFromPath(options: {
     const mcpConfig = mcpJsonMcp || frontmatterMcp
 
-    const baseName = data.name || options.defaultName
+    const baseName = String(data.name || options.defaultName)
     const skillName = namePrefix ? `${namePrefix}/${baseName}` : baseName
     const originalDescription = data.description || ""
</file context>
Suggested change
const baseName = String(data.name || options.defaultName)
const baseName = String(data.name ?? options.defaultName)
Fix with Cubic

@code-yeongyu
code-yeongyu merged commit 1ce92fd into dev Apr 15, 2026
8 checks passed
@code-yeongyu
code-yeongyu deleted the fix/bug-batch-1 branch April 15, 2026 01:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment