feat: plugin discovery (search npm/GitHub for compatible plugins)#2
Merged
Conversation
Add a zero-dependency plugin-discovery module (src/search.ts) that searches npm and GitHub for plugins compatible with a host application. Public API: - searchPlugins(): query npm + GitHub by tag/keyword, dedupe and rank candidates by signal, and return host-verified compatible plugins. - createPluginSearch(): factory that binds injectable transports (npm/GitHub fetchers) and a TTL cache for reuse. - createTtlCache(): small in-memory TTL cache for discovery results. - sourceToInstallInput(): map a discovered source to an install input. Behavior: - Host-driven verification: the host decides compatibility; discovery only gathers and ranks candidates. - GitHub rate-limit handling: detects and surfaces rate-limit responses gracefully rather than throwing. - Zero runtime dependencies; transports are injectable for testing. - 100% covered (src/search.ts + tests/search.test.ts); full src/** gate remains at 100%. Also adds the spec-driven artifacts: US-003, FR-008..FR-012, NFR-005, SpecReviews (base, failure-domain, ears-conformance, scope-boundary, index), and plan/Plan-001-plugin-discovery/**, plus edits to spec.md, the usecase/functional/non-functional indexes, NFR-001, NFR-003, and spec/tests.md. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
5cd9a54 to
c5522b4
Compare
This was referenced Jun 28, 2026
… URLs Address SR-005 gap-analysis follow-ups on src/search.ts (TDD: failing test first, then fix). None were merge-blockers; the first two are real (privacy + memory) and one is a spec/code divergence. - FND-002 (privacy + spec divergence): cacheKey keyed on token presence (auth/anon), colliding distinct tokens. Fold a stable non-secret token-id (first 8 hex of SHA-256 via node:crypto) into the key per FR-010 §Behavior; raw token never enters the key (FR-008-CON-2). Test TC-055. - FND-003 (memory): default cacheMax to 256 in createPluginSearch so the TTL cache is bounded; explicit override still honored. Tests TC-056, TC-060. - FND-004 (in-CDN path traversal): reject registry-supplied name/fullName whose path segments contain ".." or control chars before building the manifest URL; drop the candidate without fetching. FR-009-CON-1. Test TC-057. - FND-005: parseRate treats a non-finite header parse as "no rate info" (undefined) instead of surfacing NaN; cache hits now return a shallow clone rather than the shared SearchResponse reference. Tests TC-058, TC-059. - FND-001 (process): flip Plan-001 Task-001..007 status todo -> done (Task-008 publish stays pending). Spec: add FR-009-AC-9/-CON-1, FR-010-AC-8..10 (+cacheMax input), FR-011-AC-6, and the TC-055..TC-060 matrix rows. src/search.ts stays at 100% coverage; tsc/eslint/prettier clean; quire validate clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… + fix CodeQL Integrate main's npm-source-resolution (PR #3) and git-security (PR #8) work with the plugin-discovery feature (search.ts). Resolved conflicts in spec/spec.md, spec/non-functional/NFR-003, and spec/tests.md so both main's npm/git content and the discovery content survive. Renumber the discovery test cases off main's TC-001..TC-031 block: the contiguous discovery block TC-022..TC-060 shifts +10 to TC-032..TC-070 (uniform map, relative order preserved). Updated every occurrence across tests.md (FR/NFR coverage, Test Index, Constraint Boundary, Error-Path, Edge Cases, coverage-summary prose), the discovery FR files (FR-008..FR-012), and the TC tags in tests/search.test.ts. FR-004 (main) left intact. Fix 4 HIGH CodeQL js/incomplete-url-substring-sanitization alerts in tests/search.test.ts by replacing url.includes("<host>.com") routing checks with strict `new URL(url).host === "<host>"` comparisons. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a zero-dependency plugin-discovery module (
src/search.ts) that searches npm and GitHub for plugins compatible with a host application, plus its full spec-driven artifact set.Public API
searchPlugins()— query npm + GitHub by tag/keyword, dedupe and rank candidates by signal, return host-verified compatible plugins.createPluginSearch()— factory binding injectable transports (npm/GitHub fetchers) and a TTL cache for reuse.createTtlCache()— small in-memory TTL cache for discovery results.sourceToInstallInput()— map a discovered source to an install input.Behavior
src/search.ts+tests/search.test.ts); the fullsrc/**coverage gate remains at 100% on this branch.Spec-driven artifacts
spec.md, the usecase/functional/non-functional indexes, NFR-001, NFR-003, andspec/tests.md.Gates
tsc --noEmit→ cleanvitest run→ 72 passedtest:coverage(fullsrc/**) → 100% statements / branches / functions / lineseslint src/** tests/**→ cleanprettier --check→ cleanquire validate→ 0 errorsReconciliation note
This PR shares
spec.md/ NFR-003 edits and Test Case numbers (TC-022..TC-054) with the concurrentfeat/npm-source-resolutionPR. npm lands first; this branch's overlapping spec.md / NFR-003 / TC numbering will be reconciled at the second merge.🤖 Generated with Claude Code