@oss-scout/core 0.2.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.bundle.cjs +43 -39
- package/dist/cli.js +108 -1
- package/dist/commands/config.d.ts +1 -3
- package/dist/commands/config.js +1 -7
- package/dist/commands/setup.js +3 -9
- package/dist/commands/skip.d.ts +33 -0
- package/dist/commands/skip.js +89 -0
- package/dist/core/bootstrap.js +2 -2
- package/dist/core/gist-state-store.js +19 -1
- package/dist/core/issue-discovery.d.ts +3 -3
- package/dist/core/issue-discovery.js +12 -67
- package/dist/core/issue-vetting.d.ts +0 -2
- package/dist/core/issue-vetting.js +0 -4
- package/dist/core/local-state.js +2 -2
- package/dist/core/schemas.d.ts +16 -8
- package/dist/core/schemas.js +10 -4
- package/dist/core/types.d.ts +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/scout.d.ts +27 -2
- package/dist/scout.js +69 -3
- package/package.json +7 -3
package/dist/core/schemas.js
CHANGED
|
@@ -27,7 +27,6 @@ export const IssueScopeSchema = z.enum([
|
|
|
27
27
|
]);
|
|
28
28
|
export const SearchStrategySchema = z.enum([
|
|
29
29
|
"merged",
|
|
30
|
-
"orgs",
|
|
31
30
|
"starred",
|
|
32
31
|
"broad",
|
|
33
32
|
"maintained",
|
|
@@ -36,7 +35,6 @@ export const SearchStrategySchema = z.enum([
|
|
|
36
35
|
/** All concrete strategies (excludes 'all' meta-strategy). */
|
|
37
36
|
export const CONCRETE_STRATEGIES = [
|
|
38
37
|
"merged",
|
|
39
|
-
"orgs",
|
|
40
38
|
"starred",
|
|
41
39
|
"broad",
|
|
42
40
|
"maintained",
|
|
@@ -111,6 +109,14 @@ export const TrackedIssueSchema = z.object({
|
|
|
111
109
|
vetted: z.boolean(),
|
|
112
110
|
vettingResult: IssueVettingResultSchema.optional(),
|
|
113
111
|
});
|
|
112
|
+
// ── Skipped issue schema ──────────────────────────────────────────
|
|
113
|
+
export const SkippedIssueSchema = z.object({
|
|
114
|
+
url: z.string(),
|
|
115
|
+
repo: z.string(),
|
|
116
|
+
number: z.number(),
|
|
117
|
+
title: z.string(),
|
|
118
|
+
skippedAt: z.string(),
|
|
119
|
+
});
|
|
114
120
|
// ── Saved candidate schema ─────────────────────────────────────────
|
|
115
121
|
export const SavedCandidateSchema = z.object({
|
|
116
122
|
issueUrl: z.string(),
|
|
@@ -129,13 +135,12 @@ export const SavedCandidateSchema = z.object({
|
|
|
129
135
|
export const PersistenceModeSchema = z.enum(["local", "gist"]);
|
|
130
136
|
export const ScoutPreferencesSchema = z.object({
|
|
131
137
|
githubUsername: z.string().default(""),
|
|
132
|
-
languages: z.array(z.string()).default(["
|
|
138
|
+
languages: z.array(z.string()).default(["any"]),
|
|
133
139
|
labels: z.array(z.string()).default(["good first issue", "help wanted"]),
|
|
134
140
|
scope: z.array(IssueScopeSchema).optional(),
|
|
135
141
|
excludeRepos: z.array(z.string()).default([]),
|
|
136
142
|
excludeOrgs: z.array(z.string()).default([]),
|
|
137
143
|
aiPolicyBlocklist: z.array(z.string()).default(["matplotlib/matplotlib"]),
|
|
138
|
-
preferredOrgs: z.array(z.string()).default([]),
|
|
139
144
|
projectCategories: z.array(ProjectCategorySchema).default([]),
|
|
140
145
|
minStars: z.number().default(50),
|
|
141
146
|
maxIssueAgeDays: z.number().default(90),
|
|
@@ -154,6 +159,7 @@ export const ScoutStateSchema = z.object({
|
|
|
154
159
|
mergedPRs: z.array(StoredMergedPRSchema).default([]),
|
|
155
160
|
closedPRs: z.array(StoredClosedPRSchema).default([]),
|
|
156
161
|
savedResults: z.array(SavedCandidateSchema).default([]),
|
|
162
|
+
skippedIssues: z.array(SkippedIssueSchema).default([]),
|
|
157
163
|
lastSearchAt: z.string().optional(),
|
|
158
164
|
lastRunAt: z.string().default(() => new Date().toISOString()),
|
|
159
165
|
gistId: z.string().optional(),
|
package/dist/core/types.d.ts
CHANGED
|
@@ -19,7 +19,7 @@ export interface ProjectHealth {
|
|
|
19
19
|
failureReason?: string;
|
|
20
20
|
}
|
|
21
21
|
/** Priority tier for issue search results. */
|
|
22
|
-
export type SearchPriority = "merged_pr" | "
|
|
22
|
+
export type SearchPriority = "merged_pr" | "starred" | "normal";
|
|
23
23
|
/** A fully vetted issue candidate with scoring. */
|
|
24
24
|
export interface IssueCandidate {
|
|
25
25
|
issue: TrackedIssue;
|
package/dist/index.d.ts
CHANGED
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
*/
|
|
17
17
|
export { createScout, OssScout } from "./scout.js";
|
|
18
18
|
export type { ScoutConfig, SearchOptions, SearchResult, IssueCandidate, MergedPRRecord, ClosedPRRecord, RepoScoreUpdate, ProjectHealth, SearchPriority, CheckResult, VetListOptions, VetListResult, VetListEntry, VetListSummary, } from "./core/types.js";
|
|
19
|
-
export type { ScoutState, ScoutPreferences, RepoScore, RepoSignals, IssueVettingResult, ContributionGuidelines, TrackedIssue, IssueScope, ProjectCategory, StoredMergedPR, StoredClosedPR, SearchStrategy, } from "./core/schemas.js";
|
|
20
|
-
export { ScoutStateSchema, ScoutPreferencesSchema, RepoScoreSchema, IssueScopeSchema, ProjectCategorySchema, SearchStrategySchema, } from "./core/schemas.js";
|
|
19
|
+
export type { ScoutState, ScoutPreferences, RepoScore, RepoSignals, IssueVettingResult, ContributionGuidelines, TrackedIssue, IssueScope, ProjectCategory, StoredMergedPR, StoredClosedPR, SearchStrategy, SkippedIssue, } from "./core/schemas.js";
|
|
20
|
+
export { ScoutStateSchema, ScoutPreferencesSchema, RepoScoreSchema, IssueScopeSchema, ProjectCategorySchema, SearchStrategySchema, SkippedIssueSchema, } from "./core/schemas.js";
|
|
21
21
|
export { requireGitHubToken, getGitHubToken } from "./core/utils.js";
|
|
22
22
|
export { IssueDiscovery } from "./core/issue-discovery.js";
|
|
23
23
|
export { IssueVetter, type ScoutStateReader } from "./core/issue-vetting.js";
|
package/dist/index.js
CHANGED
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
// Main API
|
|
18
18
|
export { createScout, OssScout } from "./scout.js";
|
|
19
19
|
// Schemas (for consumers who need runtime validation)
|
|
20
|
-
export { ScoutStateSchema, ScoutPreferencesSchema, RepoScoreSchema, IssueScopeSchema, ProjectCategorySchema, SearchStrategySchema, } from "./core/schemas.js";
|
|
20
|
+
export { ScoutStateSchema, ScoutPreferencesSchema, RepoScoreSchema, IssueScopeSchema, ProjectCategorySchema, SearchStrategySchema, SkippedIssueSchema, } from "./core/schemas.js";
|
|
21
21
|
// Utilities
|
|
22
22
|
export { requireGitHubToken, getGitHubToken } from "./core/utils.js";
|
|
23
23
|
// Internal classes (for advanced use)
|
package/dist/scout.d.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* Implements ScoutStateReader to bridge state with the search engine.
|
|
6
6
|
*/
|
|
7
7
|
import type { ScoutStateReader } from "./core/issue-vetting.js";
|
|
8
|
-
import type { ScoutState, ScoutPreferences, RepoScore, SavedCandidate } from "./core/schemas.js";
|
|
8
|
+
import type { ScoutState, ScoutPreferences, RepoScore, SavedCandidate, SkippedIssue } from "./core/schemas.js";
|
|
9
9
|
import type { ScoutConfig, SearchOptions, SearchResult, IssueCandidate, MergedPRRecord, ClosedPRRecord, RepoScoreUpdate, ProjectCategory, VetListOptions, VetListResult } from "./core/types.js";
|
|
10
10
|
import { GistStateStore } from "./core/gist-state-store.js";
|
|
11
11
|
/**
|
|
@@ -44,6 +44,7 @@ export declare class OssScout implements ScoutStateReader {
|
|
|
44
44
|
constructor(githubToken: string, initialState: ScoutState, gistStore?: GistStateStore | null);
|
|
45
45
|
/**
|
|
46
46
|
* Multi-strategy issue search. Returns scored, sorted candidates.
|
|
47
|
+
* Automatically culls expired skip entries and filters skipped issues.
|
|
47
48
|
*/
|
|
48
49
|
search(options?: SearchOptions): Promise<SearchResult>;
|
|
49
50
|
/**
|
|
@@ -59,7 +60,6 @@ export declare class OssScout implements ScoutStateReader {
|
|
|
59
60
|
private classifyVetResult;
|
|
60
61
|
getReposWithMergedPRs(): string[];
|
|
61
62
|
getStarredRepos(): string[];
|
|
62
|
-
getPreferredOrgs(): string[];
|
|
63
63
|
getProjectCategories(): ProjectCategory[];
|
|
64
64
|
getRepoScore(repo: string): number | null;
|
|
65
65
|
/** Get current preferences (read-only). */
|
|
@@ -101,6 +101,31 @@ export declare class OssScout implements ScoutStateReader {
|
|
|
101
101
|
* Clear all saved results.
|
|
102
102
|
*/
|
|
103
103
|
clearResults(): void;
|
|
104
|
+
/**
|
|
105
|
+
* Skip an issue — excludes it from future searches. Auto-culled after 90 days.
|
|
106
|
+
*/
|
|
107
|
+
skipIssue(url: string, metadata?: {
|
|
108
|
+
repo?: string;
|
|
109
|
+
number?: number;
|
|
110
|
+
title?: string;
|
|
111
|
+
}): void;
|
|
112
|
+
/**
|
|
113
|
+
* Get all skipped issues.
|
|
114
|
+
*/
|
|
115
|
+
getSkippedIssues(): SkippedIssue[];
|
|
116
|
+
/**
|
|
117
|
+
* Remove a specific issue from the skip list.
|
|
118
|
+
*/
|
|
119
|
+
unskipIssue(url: string): void;
|
|
120
|
+
/**
|
|
121
|
+
* Clear all skipped issues.
|
|
122
|
+
*/
|
|
123
|
+
clearSkippedIssues(): void;
|
|
124
|
+
/**
|
|
125
|
+
* Remove skipped issues older than maxDays (default 90). Called automatically during search.
|
|
126
|
+
* @returns The number of expired entries that were removed.
|
|
127
|
+
*/
|
|
128
|
+
cullExpiredSkips(maxDays?: number): number;
|
|
104
129
|
/**
|
|
105
130
|
* Check if state has uncommitted changes.
|
|
106
131
|
*/
|
package/dist/scout.js
CHANGED
|
@@ -119,12 +119,17 @@ export class OssScout {
|
|
|
119
119
|
// ── Search ──────────────────────────────────────────────────────────
|
|
120
120
|
/**
|
|
121
121
|
* Multi-strategy issue search. Returns scored, sorted candidates.
|
|
122
|
+
* Automatically culls expired skip entries and filters skipped issues.
|
|
122
123
|
*/
|
|
123
124
|
async search(options) {
|
|
125
|
+
// Auto-cull expired skips before searching
|
|
126
|
+
this.cullExpiredSkips();
|
|
127
|
+
const skippedUrls = new Set((this.state.skippedIssues ?? []).map((s) => s.url));
|
|
124
128
|
const discovery = new IssueDiscovery(this.githubToken, this.state.preferences, this);
|
|
125
129
|
const { candidates, strategiesUsed } = await discovery.searchIssues({
|
|
126
130
|
maxResults: options?.maxResults,
|
|
127
131
|
strategies: options?.strategies,
|
|
132
|
+
skippedUrls,
|
|
128
133
|
});
|
|
129
134
|
this.state.lastSearchAt = new Date().toISOString();
|
|
130
135
|
this.dirty = true;
|
|
@@ -234,9 +239,6 @@ export class OssScout {
|
|
|
234
239
|
getStarredRepos() {
|
|
235
240
|
return this.state.starredRepos;
|
|
236
241
|
}
|
|
237
|
-
getPreferredOrgs() {
|
|
238
|
-
return this.state.preferences.preferredOrgs;
|
|
239
|
-
}
|
|
240
242
|
getProjectCategories() {
|
|
241
243
|
return this.state.preferences.projectCategories;
|
|
242
244
|
}
|
|
@@ -369,6 +371,70 @@ export class OssScout {
|
|
|
369
371
|
this.state.savedResults = [];
|
|
370
372
|
this.dirty = true;
|
|
371
373
|
}
|
|
374
|
+
// ── Skip List ───────────────────────────────────────────────────────
|
|
375
|
+
/**
|
|
376
|
+
* Skip an issue — excludes it from future searches. Auto-culled after 90 days.
|
|
377
|
+
*/
|
|
378
|
+
skipIssue(url, metadata) {
|
|
379
|
+
const existing = this.state.skippedIssues ?? [];
|
|
380
|
+
if (existing.some((s) => s.url === url))
|
|
381
|
+
return; // already skipped
|
|
382
|
+
this.state.skippedIssues = [
|
|
383
|
+
...existing,
|
|
384
|
+
{
|
|
385
|
+
url,
|
|
386
|
+
repo: metadata?.repo ?? "",
|
|
387
|
+
number: metadata?.number ?? 0,
|
|
388
|
+
title: metadata?.title ?? "",
|
|
389
|
+
skippedAt: new Date().toISOString(),
|
|
390
|
+
},
|
|
391
|
+
];
|
|
392
|
+
// Also remove from saved results if present
|
|
393
|
+
if (this.state.savedResults) {
|
|
394
|
+
this.state.savedResults = this.state.savedResults.filter((r) => r.issueUrl !== url);
|
|
395
|
+
}
|
|
396
|
+
this.dirty = true;
|
|
397
|
+
}
|
|
398
|
+
/**
|
|
399
|
+
* Get all skipped issues.
|
|
400
|
+
*/
|
|
401
|
+
getSkippedIssues() {
|
|
402
|
+
return this.state.skippedIssues ?? [];
|
|
403
|
+
}
|
|
404
|
+
/**
|
|
405
|
+
* Remove a specific issue from the skip list.
|
|
406
|
+
*/
|
|
407
|
+
unskipIssue(url) {
|
|
408
|
+
this.state.skippedIssues = (this.state.skippedIssues ?? []).filter((s) => s.url !== url);
|
|
409
|
+
this.dirty = true;
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* Clear all skipped issues.
|
|
413
|
+
*/
|
|
414
|
+
clearSkippedIssues() {
|
|
415
|
+
this.state.skippedIssues = [];
|
|
416
|
+
this.dirty = true;
|
|
417
|
+
}
|
|
418
|
+
/**
|
|
419
|
+
* Remove skipped issues older than maxDays (default 90). Called automatically during search.
|
|
420
|
+
* @returns The number of expired entries that were removed.
|
|
421
|
+
*/
|
|
422
|
+
cullExpiredSkips(maxDays = 90) {
|
|
423
|
+
const cutoff = new Date();
|
|
424
|
+
cutoff.setDate(cutoff.getDate() - maxDays);
|
|
425
|
+
const before = (this.state.skippedIssues ?? []).length;
|
|
426
|
+
this.state.skippedIssues = (this.state.skippedIssues ?? []).filter((s) => {
|
|
427
|
+
const d = new Date(s.skippedAt);
|
|
428
|
+
if (isNaN(d.getTime())) {
|
|
429
|
+
return true; // keep entries with invalid dates rather than silently dropping
|
|
430
|
+
}
|
|
431
|
+
return d >= cutoff;
|
|
432
|
+
});
|
|
433
|
+
const culled = before - this.state.skippedIssues.length;
|
|
434
|
+
if (culled > 0)
|
|
435
|
+
this.dirty = true;
|
|
436
|
+
return culled;
|
|
437
|
+
}
|
|
372
438
|
// ── Persistence ─────────────────────────────────────────────────────
|
|
373
439
|
/**
|
|
374
440
|
* Check if state has uncommitted changes.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oss-scout/core",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "Personalized GitHub issue finder with multi-strategy search, deep vetting, and viability scoring — CLI, library, MCP server, and Claude Code plugin",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
7
7
|
"oss-scout": "./dist/cli.bundle.cjs"
|
|
@@ -37,7 +37,11 @@
|
|
|
37
37
|
"issue-discovery",
|
|
38
38
|
"cli",
|
|
39
39
|
"vetting",
|
|
40
|
-
"contributions"
|
|
40
|
+
"contributions",
|
|
41
|
+
"claude",
|
|
42
|
+
"mcp-server",
|
|
43
|
+
"contribution-finder",
|
|
44
|
+
"personalized"
|
|
41
45
|
],
|
|
42
46
|
"author": "John Costa",
|
|
43
47
|
"license": "MIT",
|