@oss-scout/core 0.4.0 → 0.6.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.
@@ -64,6 +64,11 @@ export declare const StoredClosedPRSchema: z.ZodObject<{
64
64
  title: z.ZodString;
65
65
  closedAt: z.ZodString;
66
66
  }, z.core.$strip>;
67
+ export declare const StoredOpenPRSchema: z.ZodObject<{
68
+ url: z.ZodString;
69
+ title: z.ZodString;
70
+ openedAt: z.ZodString;
71
+ }, z.core.$strip>;
67
72
  export declare const ContributionGuidelinesSchema: z.ZodObject<{
68
73
  branchNamingConvention: z.ZodOptional<z.ZodString>;
69
74
  commitMessageFormat: z.ZodOptional<z.ZodString>;
@@ -80,6 +85,16 @@ export declare const ContributionGuidelinesSchema: z.ZodObject<{
80
85
  claRequired: z.ZodOptional<z.ZodBoolean>;
81
86
  rawContent: z.ZodOptional<z.ZodString>;
82
87
  }, z.core.$strip>;
88
+ export declare const LinkedPRSchema: z.ZodObject<{
89
+ number: z.ZodNumber;
90
+ author: z.ZodString;
91
+ state: z.ZodEnum<{
92
+ closed: "closed";
93
+ open: "open";
94
+ }>;
95
+ merged: z.ZodBoolean;
96
+ url: z.ZodString;
97
+ }, z.core.$strip>;
83
98
  export declare const IssueVettingResultSchema: z.ZodObject<{
84
99
  passedAllChecks: z.ZodBoolean;
85
100
  checks: z.ZodObject<{
@@ -105,6 +120,16 @@ export declare const IssueVettingResultSchema: z.ZodObject<{
105
120
  claRequired: z.ZodOptional<z.ZodBoolean>;
106
121
  rawContent: z.ZodOptional<z.ZodString>;
107
122
  }, z.core.$strip>>;
123
+ linkedPR: z.ZodOptional<z.ZodNullable<z.ZodObject<{
124
+ number: z.ZodNumber;
125
+ author: z.ZodString;
126
+ state: z.ZodEnum<{
127
+ closed: "closed";
128
+ open: "open";
129
+ }>;
130
+ merged: z.ZodBoolean;
131
+ url: z.ZodString;
132
+ }, z.core.$strip>>>;
108
133
  notes: z.ZodArray<z.ZodString>;
109
134
  }, z.core.$strip>;
110
135
  export declare const TrackedIssueSchema: z.ZodObject<{
@@ -148,6 +173,16 @@ export declare const TrackedIssueSchema: z.ZodObject<{
148
173
  claRequired: z.ZodOptional<z.ZodBoolean>;
149
174
  rawContent: z.ZodOptional<z.ZodString>;
150
175
  }, z.core.$strip>>;
176
+ linkedPR: z.ZodOptional<z.ZodNullable<z.ZodObject<{
177
+ number: z.ZodNumber;
178
+ author: z.ZodString;
179
+ state: z.ZodEnum<{
180
+ closed: "closed";
181
+ open: "open";
182
+ }>;
183
+ merged: z.ZodBoolean;
184
+ url: z.ZodString;
185
+ }, z.core.$strip>>>;
151
186
  notes: z.ZodArray<z.ZodString>;
152
187
  }, z.core.$strip>>;
153
188
  }, z.core.$strip>;
@@ -287,6 +322,11 @@ export declare const ScoutStateSchema: z.ZodObject<{
287
322
  title: z.ZodString;
288
323
  closedAt: z.ZodString;
289
324
  }, z.core.$strip>>>;
325
+ openPRs: z.ZodDefault<z.ZodArray<z.ZodObject<{
326
+ url: z.ZodString;
327
+ title: z.ZodString;
328
+ openedAt: z.ZodString;
329
+ }, z.core.$strip>>>;
290
330
  savedResults: z.ZodDefault<z.ZodArray<z.ZodObject<{
291
331
  issueUrl: z.ZodString;
292
332
  repo: z.ZodString;
@@ -322,7 +362,9 @@ export type RepoSignals = z.infer<typeof RepoSignalsSchema>;
322
362
  export type RepoScore = z.infer<typeof RepoScoreSchema>;
323
363
  export type StoredMergedPR = z.infer<typeof StoredMergedPRSchema>;
324
364
  export type StoredClosedPR = z.infer<typeof StoredClosedPRSchema>;
365
+ export type StoredOpenPR = z.infer<typeof StoredOpenPRSchema>;
325
366
  export type ContributionGuidelines = z.infer<typeof ContributionGuidelinesSchema>;
367
+ export type LinkedPR = z.infer<typeof LinkedPRSchema>;
326
368
  export type IssueVettingResult = z.infer<typeof IssueVettingResultSchema>;
327
369
  export type TrackedIssue = z.infer<typeof TrackedIssueSchema>;
328
370
  export type ScoutPreferences = z.infer<typeof ScoutPreferencesSchema>;
@@ -67,6 +67,11 @@ export const StoredClosedPRSchema = z.object({
67
67
  title: z.string(),
68
68
  closedAt: z.string(),
69
69
  });
70
+ export const StoredOpenPRSchema = z.object({
71
+ url: z.string(),
72
+ title: z.string(),
73
+ openedAt: z.string(),
74
+ });
70
75
  // ── Contribution schemas ────────────────────────────────────────────
71
76
  export const ContributionGuidelinesSchema = z.object({
72
77
  branchNamingConvention: z.string().optional(),
@@ -84,6 +89,13 @@ export const ContributionGuidelinesSchema = z.object({
84
89
  claRequired: z.boolean().optional(),
85
90
  rawContent: z.string().optional(),
86
91
  });
92
+ export const LinkedPRSchema = z.object({
93
+ number: z.number(),
94
+ author: z.string(),
95
+ state: z.enum(["open", "closed"]),
96
+ merged: z.boolean(),
97
+ url: z.string(),
98
+ });
87
99
  export const IssueVettingResultSchema = z.object({
88
100
  passedAllChecks: z.boolean(),
89
101
  checks: z.object({
@@ -94,6 +106,7 @@ export const IssueVettingResultSchema = z.object({
94
106
  contributionGuidelinesFound: z.boolean(),
95
107
  }),
96
108
  contributionGuidelines: ContributionGuidelinesSchema.optional(),
109
+ linkedPR: LinkedPRSchema.nullable().optional(),
97
110
  notes: z.array(z.string()),
98
111
  });
99
112
  export const TrackedIssueSchema = z.object({
@@ -161,6 +174,7 @@ export const ScoutStateSchema = z.object({
161
174
  starredReposLastFetched: z.string().optional(),
162
175
  mergedPRs: z.array(StoredMergedPRSchema).default([]),
163
176
  closedPRs: z.array(StoredClosedPRSchema).default([]),
177
+ openPRs: z.array(StoredOpenPRSchema).default([]),
164
178
  savedResults: z.array(SavedCandidateSchema).default([]),
165
179
  skippedIssues: z.array(SkippedIssueSchema).default([]),
166
180
  lastSearchAt: z.string().optional(),
@@ -2,7 +2,7 @@
2
2
  * Core types for oss-scout — ephemeral types that are never persisted.
3
3
  */
4
4
  import type { RepoSignals, TrackedIssue, IssueVettingResult, IssueScope, ScoutState, SearchStrategy } from "./schemas.js";
5
- export type { ProjectCategory, IssueScope, RepoSignals, RepoScore, StoredMergedPR, StoredClosedPR, ContributionGuidelines, IssueVettingResult, TrackedIssue, ScoutPreferences, SavedCandidate, ScoutState, SearchStrategy, } from "./schemas.js";
5
+ export type { ProjectCategory, IssueScope, RepoSignals, RepoScore, StoredMergedPR, StoredClosedPR, ContributionGuidelines, IssueVettingResult, LinkedPR, TrackedIssue, ScoutPreferences, SavedCandidate, ScoutState, SearchStrategy, } from "./schemas.js";
6
6
  /** Health snapshot of a GitHub repository. */
7
7
  export interface ProjectHealth {
8
8
  repo: string;
@@ -20,11 +20,20 @@ export interface ProjectHealth {
20
20
  }
21
21
  /** Priority tier for issue search results. */
22
22
  export type SearchPriority = "merged_pr" | "starred" | "normal";
23
+ /** Source file the anti-LLM policy match came from, or null when no file matched. */
24
+ export type AntiLLMPolicySourceFile = "CONTRIBUTING.md" | "CODE_OF_CONDUCT.md" | "README.md";
25
+ /** Result of scanning a repo's policy docs for anti-LLM/AI keywords. */
26
+ export interface AntiLLMPolicyResult {
27
+ matched: boolean;
28
+ matchedKeywords: string[];
29
+ sourceFile: AntiLLMPolicySourceFile | null;
30
+ }
23
31
  /** A fully vetted issue candidate with scoring. */
24
32
  export interface IssueCandidate {
25
33
  issue: TrackedIssue;
26
34
  vettingResult: IssueVettingResult;
27
35
  projectHealth: ProjectHealth;
36
+ antiLLMPolicy: AntiLLMPolicyResult;
28
37
  recommendation: "approve" | "skip" | "needs_review";
29
38
  reasonsToSkip: string[];
30
39
  reasonsToApprove: string[];
@@ -122,3 +131,10 @@ export interface ClosedPRRecord {
122
131
  closedAt: string;
123
132
  repo: string;
124
133
  }
134
+ /** Record of an open PR for state contribution. */
135
+ export interface OpenPRRecord {
136
+ url: string;
137
+ title: string;
138
+ openedAt: string;
139
+ repo: string;
140
+ }
package/dist/index.d.ts CHANGED
@@ -15,9 +15,10 @@
15
15
  * @packageDocumentation
16
16
  */
17
17
  export { createScout, OssScout } from "./scout.js";
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, SkippedIssue, } from "./core/schemas.js";
18
+ export type { ScoutConfig, SearchOptions, SearchResult, IssueCandidate, MergedPRRecord, ClosedPRRecord, OpenPRRecord, RepoScoreUpdate, ProjectHealth, SearchPriority, CheckResult, AntiLLMPolicyResult, AntiLLMPolicySourceFile, VetListOptions, VetListResult, VetListEntry, VetListSummary, } from "./core/types.js";
19
+ export type { ScoutState, ScoutPreferences, RepoScore, RepoSignals, IssueVettingResult, LinkedPR, ContributionGuidelines, TrackedIssue, IssueScope, ProjectCategory, StoredMergedPR, StoredClosedPR, StoredOpenPR, SearchStrategy, SkippedIssue, } from "./core/schemas.js";
20
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";
24
+ export { scanForAntiLLMPolicy, ANTI_LLM_KEYWORDS, } from "./core/anti-llm-policy.js";
package/dist/index.js CHANGED
@@ -23,3 +23,4 @@ export { requireGitHubToken, getGitHubToken } from "./core/utils.js";
23
23
  // Internal classes (for advanced use)
24
24
  export { IssueDiscovery } from "./core/issue-discovery.js";
25
25
  export { IssueVetter } from "./core/issue-vetting.js";
26
+ export { scanForAntiLLMPolicy, ANTI_LLM_KEYWORDS, } from "./core/anti-llm-policy.js";
package/dist/scout.d.ts CHANGED
@@ -6,7 +6,7 @@
6
6
  */
7
7
  import type { ScoutStateReader } from "./core/issue-vetting.js";
8
8
  import type { ScoutState, ScoutPreferences, RepoScore, SavedCandidate, SkippedIssue } from "./core/schemas.js";
9
- import type { ScoutConfig, SearchOptions, SearchResult, IssueCandidate, MergedPRRecord, ClosedPRRecord, RepoScoreUpdate, ProjectCategory, VetListOptions, VetListResult } from "./core/types.js";
9
+ import type { ScoutConfig, SearchOptions, SearchResult, IssueCandidate, MergedPRRecord, ClosedPRRecord, OpenPRRecord, RepoScoreUpdate, ProjectCategory, VetListOptions, VetListResult } from "./core/types.js";
10
10
  import { GistStateStore } from "./core/gist-state-store.js";
11
11
  /**
12
12
  * Create an OssScout instance.
@@ -59,6 +59,7 @@ export declare class OssScout implements ScoutStateReader {
59
59
  vetList(options?: VetListOptions): Promise<VetListResult>;
60
60
  private classifyVetResult;
61
61
  getReposWithMergedPRs(): string[];
62
+ getReposWithOpenPRs(): string[];
62
63
  getStarredRepos(): string[];
63
64
  getProjectCategories(): ProjectCategory[];
64
65
  getRepoScore(repo: string): number | null;
@@ -75,6 +76,11 @@ export declare class OssScout implements ScoutStateReader {
75
76
  * Record that a PR was closed without merge.
76
77
  */
77
78
  recordClosedPR(pr: ClosedPRRecord): void;
79
+ /**
80
+ * Record that a PR is currently open in this repo.
81
+ * Open PRs signal active engagement even when nothing is merged yet.
82
+ */
83
+ recordOpenPR(pr: OpenPRRecord): void;
78
84
  /**
79
85
  * Update repo score with observed signals.
80
86
  */
package/dist/scout.js CHANGED
@@ -236,6 +236,18 @@ export class OssScout {
236
236
  .sort((a, b) => b[1] - a[1])
237
237
  .map(([repo]) => repo);
238
238
  }
239
+ getReposWithOpenPRs() {
240
+ const repoCounts = new Map();
241
+ for (const pr of this.state.openPRs ?? []) {
242
+ const repo = extractRepoFromUrl(pr.url);
243
+ if (repo) {
244
+ repoCounts.set(repo, (repoCounts.get(repo) ?? 0) + 1);
245
+ }
246
+ }
247
+ return [...repoCounts.entries()]
248
+ .sort((a, b) => b[1] - a[1])
249
+ .map(([repo]) => repo);
250
+ }
239
251
  getStarredRepos() {
240
252
  return this.state.starredRepos;
241
253
  }
@@ -285,6 +297,20 @@ export class OssScout {
285
297
  this.updateRepoScoreFromPRs(pr.repo);
286
298
  this.dirty = true;
287
299
  }
300
+ /**
301
+ * Record that a PR is currently open in this repo.
302
+ * Open PRs signal active engagement even when nothing is merged yet.
303
+ */
304
+ recordOpenPR(pr) {
305
+ const existing = this.state.openPRs ?? [];
306
+ if (existing.some((p) => p.url === pr.url))
307
+ return;
308
+ this.state.openPRs = [
309
+ ...existing,
310
+ { url: pr.url, title: pr.title, openedAt: pr.openedAt },
311
+ ];
312
+ this.dirty = true;
313
+ }
288
314
  /**
289
315
  * Update repo score with observed signals.
290
316
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oss-scout/core",
3
- "version": "0.4.0",
3
+ "version": "0.6.0",
4
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": {
@@ -55,11 +55,12 @@
55
55
  },
56
56
  "devDependencies": {
57
57
  "@types/node": "^25.5.0",
58
- "@vitest/coverage-v8": "^4.1.0",
58
+ "@vitest/coverage-v8": "^4.1.4",
59
59
  "esbuild": "^0.27.4",
60
60
  "tsx": "^4.21.0",
61
61
  "typescript": "^5.9.3",
62
- "vitest": "^4.1.0"
62
+ "vite": "^8.0.5",
63
+ "vitest": "^4.1.4"
63
64
  },
64
65
  "scripts": {
65
66
  "build": "tsc",