fix: make command loading resilient to MCP/Skill failures

Merged
AN
7mo ago
+456-47

Summary

  • Wrap MCP prompt loading and Skill loading in individual try/catch blocks in command/index.ts so that default commands (init, discover, review) are always served even when plugins fail
  • Add safe() error wrapper around each non-blocking sync request in sync.tsx so one failing request doesn't silently prevent all others (including commands) from populating the TUI store
  • Add 22 tests covering command resilience, default command properties, and the safe wrapper pattern

Root Cause

When MCP.prompts() or Skill.all() threw during command state initialization, the entire state promise rejected — all default commands including /discover disappeared from the TUI. Additionally, the non-blocking Promise.all in sync.tsx was fire-and-forget with no error handler, so failures were silently swallowed and setStore("status", "complete") never ran.

Changes

FileChange
src/command/index.tsWrap MCP and Skill loading in try/catch
src/cli/cmd/tui/context/sync.tsxAdd safe() wrapper for individual error handling
test/command/command-resilience.test.ts15 tests for command defaults, properties, and resilience pattern
test/command/sync-resilience.test.ts7 tests for the safe() wrapper pattern

Test plan

  • All 1388 existing tests pass
  • 22 new tests pass covering:
    • Default commands (init, discover, review) always present
    • Discover command has correct metadata and template
    • Resilience pattern: MCP failure, Skill failure, both failures
    • Skills can't overwrite default commands
    • safe() wrapper: individual failures, all failures, non-Error rejections
    • Contrasts old behavior (Promise.all rejects) vs new (always resolves)

šŸ¤– Generated with Claude Code