Skip to content

WIP - feat(ways): plugin way discovery (ADR-129)#76

Open
ctracey wants to merge 4 commits into
aaronsb:mainfrom
ctracey:feat/plugin-way-discovery
Open

WIP - feat(ways): plugin way discovery (ADR-129)#76
ctracey wants to merge 4 commits into
aaronsb:mainfrom
ctracey:feat/plugin-way-discovery

Conversation

@ctracey
Copy link
Copy Markdown

@ctracey ctracey commented Apr 25, 2026

Summary

Extends the way discovery system to scan enabled Claude Code plugins for ways, enabling plugin authors to ship domain-specific guidance alongside their tools.

  • Hybrid discovery: Session-start hook resolves plugin paths once via claude plugin list --json, writes a session manifest; per-invocation scans read from the manifest
  • Three-tier precedence: project-local > plugin > global (existing ways always win)
  • ID namespacing: Plugin ways prefixed as plugin:{plugin_id}/{way_path} to prevent collisions
  • Corpus integration: ways corpus discovers plugin ways outside sessions via installed_plugins.json
  • Macro trust: Plugin macros execute without trust prompts (plugins are already user-approved)
  • Scope filtering: Project-scoped plugins only surface their ways when the active project matches

Architecture

Design documented in ADR-129. Key decisions:

  1. Session manifest over per-scan CLI callsclaude plugin list is too slow to run on every hook invocation; resolving once at session start amortizes the cost
  2. Fallback chain — File resolution tries installed_plugins.json first (fast, no session context needed), then falls back to session manifest
  3. No version dedup — Plugin registry already ensures one enabled version per ID; we trust the registry rather than reimplementing version logic

Changes

Area Files What
Hook hooks/ways/resolve-plugins.sh Session-start hook that queries plugin CLI, writes manifest
Config settings.json Registers the new hook in SessionStart chain
Discovery src/cmd/scan/candidates.rs collect_plugin_candidates(), prefixed dir scanning
Resolution src/session.rs plugin_way_dirs(), resolve_way_file_in_session(), fallback chain
Show src/cmd/show/mod.rs Session-aware file resolution for ways and checks
Corpus src/cmd/corpus.rs Plugin way discovery for offline corpus builds
ADR docs/architecture/system/ADR-129-* Design document

Test plan

9 scenarios covering the plugin discovery surface, documented in SIMULATION-SPEC.md §9:

  • 9a — Plugin way appears in scan candidates with plugin: prefix
  • 9b — Plugin way fires through show::way pipeline (markers stamped)
  • 9c — Multiple plugins merge into unified candidate list
  • 9d — Project-local way with same ID shadows plugin way
  • 9e — Project-scoped plugin excluded from non-matching project
  • 9f — Plugin check fires and pulls parent way
  • 9g — Missing/empty manifest degrades gracefully (zero candidates)
  • 9h — Plugin macro executes without trust gate
  • 9i — Disabled plugin excluded from manifest

All 19 tests pass (9 new + 10 existing, zero regressions):

test scenario_11a_plugin_way_in_scan ... ok
test scenario_11b_plugin_way_fires ... ok
test scenario_11c_multi_plugin_merge ... ok
test scenario_11d_project_shadows_plugin ... ok
test scenario_11e_project_scope_filter ... ok
test scenario_11f_plugin_check_fires ... ok
test scenario_11g_missing_manifest ... ok
test scenario_11h_plugin_macro_runs ... ok
test scenario_11i_disabled_plugin_excluded ... ok

ctracey added 2 commits April 25, 2026 12:21
Design for extending way discovery to scan enabled Claude Code plugins.
Hybrid approach: resolve plugin paths once at session start via
`claude plugin list --json`, write a session manifest, and scan
plugin hooks/ways/ directories alongside project-local and global.
Extend way discovery to scan enabled Claude Code plugins for ways.
At session start, resolve-plugins.sh queries `claude plugin list --json`
and writes a manifest of plugin hooks/ways/ paths. The ways binary reads
this manifest during scans, inserting plugin ways between project-local
and global priority.

Implementation:
- resolve-plugins.sh: session-start hook writing plugin-ways.json
- candidates.rs: collect_candidates/collect_checks gain plugin source
- session.rs: PluginWayEntry, plugin_way_dirs(), resolve_plugin_way_dir()
- corpus.rs: discover_plugin_way_dirs() for embedding corpus inclusion
- show/mod.rs: session-aware resolve for plugin way file lookup

Tests: 9 integration scenarios (11a-11i) covering keyword match,
idempotency, missing manifest fallback, project-scope filtering,
global coexistence, multiple plugins, check files, and macro trust.
All 19 simulation tests pass with zero regressions.
@ctracey ctracey changed the title feat(ways): plugin way discovery (ADR-129) WIP - feat(ways): plugin way discovery (ADR-129) Apr 25, 2026
@ctracey
Copy link
Copy Markdown
Author

ctracey commented Apr 25, 2026

TODO

  • complete manual user review
  • add docs regarding plugin support
  • make sure ways rethink is working with plugins

ctracey added 2 commits April 27, 2026 11:11
Plugin ways use $PLUGIN_INSTALL_PATH/ways/ (no hooks/ways/ fallback).
Consolidated shell+Rust plugin resolution into a single Rust
implementation: `ways resolve-plugins --session <id>` writes the
manifest, resolve_plugins_live() queries the CLI, both share the
same filtering and path logic. Shell hook is now a thin wrapper.

ADR-129 updated with full way file path convention for all three
scopes (global, project-local, plugin).
New flag lists all ways that would be candidates for a given project
path — global, project-local, and plugin — grouped by source. Uses
the same collect_candidates pipeline as scan, with when: precondition
filtering. Plugin discovery runs live via `claude plugin list --json`
so it always reflects current state (no stale session manifests).

Includes --project and --json flags, scenario 12 integration tests.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant