Plugin manifests that declare a directory entry (e.g. pi-goal's
`"pi": { "extensions": [".pi/extensions/pi-goal"] }`) were
pushed through to the legacy module loader unchanged. `Bun.file()`
on a directory throws "Directories cannot be read like files",
so every such plugin failed to load.
`resolvePluginPaths` now routes each joined manifest entry through
`resolveManifestEntryFile`, which:
- returns the path as-is when it is a file,
- returns the directory's `index.{ts,js,mjs,cjs}` when it is a
directory containing one of those files,
- otherwise returns null (skip).
This mirrors the documented native auto-discovery behavior in
`resolveExtensionEntries` and the candidate list in
`extensibility/custom-commands/loader.ts`.
Closes#1001.
- Updated plugin extension discovery test to use XDG_DATA_HOME instead of HOME for environment isolation.
- Replaced manual path construction with getPluginsDir() utility for consistency.
- Added XDG directory structure setup and path cache rebuild to ensure correct plugin resolution.
- Added `toExtensionId()` method to all capability types for granular extension identification and disabling.
- Added `disabledExtensions` and `includeDisabled` options to LoadOptions for filtering disabled capabilities by extension ID.
- Added plugin manifest support for `extensions` entry points with automatic discovery from installed plugins.
- Fixed skill loading to properly respect disabled skill names from custom directories.
- Improved cross-platform path handling by using `path.basename()` instead of string splitting in context file and state manager.
- Refactored capability index loading to validate source metadata and filter disabled extensions before processing.