discoverAgents sorted the listOmpExtensionRoots result by level, which
demoted CLI-injected roots (hard-coded level user) below any project
extensions: settings entry. The sibling skills/hooks/tools surface in
discovery/omp-plugins.ts consumes the returned order verbatim, so an
explicit --extension override could run a different agent than the rest
of its own plugin surface.
Drop the sort and append roots in returned order. Refresh the
discoverAgents doc comment to document the source-precedence chain (CLI
> project settings > user settings > installed plugins) and add a
regression test where a CLI-injected extension wins over a project
extensions: settings extension that defines the same agent name.
Fixes#3920
Gate the OMP extension-package agents/ scan on the omp-plugins provider so
disabledProviders suppresses plugin-shipped task agents consistently with
other extension-package surfaces.
Add a regression test covering an installed npm plugin with agents/ while
omp-plugins is disabled.
Fixes#3920
discoverAgents only walked .omp/agents and Claude marketplace plugin
roots, so agents shipped by OMP npm plugins (omp plugin install ...) and
--extension/extensions: settings roots silently disappeared while their
sibling skills/, hooks/, tools/ subdirectories were already discovered.
Route the same listOmpExtensionRoots scan used by discovery/omp-plugins.ts
through discoverAgents and append <root>/agents to the ordered scan list,
project scope before user. listOmpExtensionRoots already filters Claude
marketplace installs by realpath so they continue to flow only through
the claude-plugins provider.
Fixes#3920
Migrate 203 test files (356 call sites) from fs.rm/fs.rmSync to
removeWithRetries/removeSyncWithRetries to reduce EBUSY test failures
on Windows. removeWithRetries is now exported from @oh-my-pi/pi-utils.
The migration uses a regex-based approach that:
- Replaces fs.rm(path, { recursive, force }) → removeWithRetries(path)
- Replaces fs.rmSync(path, { recursive, force }) → removeSyncWithRetries(path)
- Replaces fs.rm(path) → removeWithRetries(path) (no options)
- Skips fs.rm/fs.rmSync inside template literals (bun --eval scripts)
- Adds imports to existing @oh-my-pi/pi-utils import or creates new one
- Removes unused fs imports where fs.rm was the only fs usage (4 files)
Stopped task-agent discovery from loading direct .claude/agents roots, while preserving OMP-native .omp agents and Claude marketplace plugin agents. Added a focused regression test for user and project Claude Code custom agent files.\n\nFixes #2209