Skip to content

Break up context.py: finish the discovery/orchestrator decomposition #470

Description

@not-stbenjam

context.py is 1,374 lines after the codex-plugin-rules refactor series (#464#469) — down from its 1,711 peak, but still ~500 lines over its pre-Codex size (873 on main), and it is doing at least four jobs. #469 established the pattern (discovery/codex.py: state-free evidence-gathering, context as the stateful orchestrator holding caches and rendering the provenance verdict). This issue tracks finishing the decomposition along the same seam.

Candidate extractions

  1. discovery/claude.py — the Claude-side discovery walks: plugins/ directory scan, marketplace-source resolution, .claude handling, and the skill discovery walks (_discover_skills*). Largest remaining block, and it mirrors Extract Codex discovery into skillsaw.discovery; context stays the orchestrator #469 exactly: state-free functions taking explicit roots/predicates, caches stay on RepositoryContext.
  2. Repo-type detection — the marker-probing that computes repo_types. Either discovery/detect.py or folded into the per-ecosystem discovery modules with the context composing the result.
  3. Exclusion machinerypath_matches_patterns, _pattern_variants, apply_excludes support. Ecosystem-neutral; plausible home alongside paths.py.

What must NOT move (doctrine, established in #465#469)

  • PluginProvenance + provenance() + the ownership views (in_format_scope, is_codex_only_plugin, codex_plugin_owning, claim-set/boundary helpers): ownership is decided in exactly one place, and that place is the context.
  • Every cache and its invalidation semantics (_provenance_cache + apply_excludes clearing, discovery slots, _UNSET sentinels, the never-cached --type-invariant enumeration path). Module-level caching would be a behavior change.
  • The public RepositoryContext API — rules and the lint tree import from skillsaw.context; methods delegate internally, signatures frozen.

Acceptance shape (per extraction PR)

Same gates the #469 PR used: full suite green, openai/plugins canary identical (total + per-rule), ai-helpers byte-identical, --type invariance spot-checks, verbatim moved bodies, a state-free boundary test (discovery imports nothing from context), docs recipe updated. Target end state: context.py under ~900 lines — the repository model, the provenance authority, and nothing else.

Not a blocker for the feature branch's merge to main — this debt is now structural and well-fenced, and each extraction is a small standalone PR against main afterward.

Related: #463 (safe-resolve sweep / banned-API ratchet, partially landed via the branch's tests/test_banned_apis.py).

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions