@oss-scout/core 0.2.0 → 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.
Files changed (56) hide show
  1. package/dist/cli.bundle.cjs +51 -47
  2. package/dist/cli.js +218 -87
  3. package/dist/commands/config.d.ts +2 -4
  4. package/dist/commands/config.js +76 -78
  5. package/dist/commands/results.d.ts +1 -1
  6. package/dist/commands/results.js +1 -1
  7. package/dist/commands/search.d.ts +2 -2
  8. package/dist/commands/search.js +16 -6
  9. package/dist/commands/setup.d.ts +1 -1
  10. package/dist/commands/setup.js +25 -25
  11. package/dist/commands/skip.d.ts +33 -0
  12. package/dist/commands/skip.js +89 -0
  13. package/dist/commands/validation.d.ts +1 -1
  14. package/dist/commands/validation.js +1 -1
  15. package/dist/commands/vet-list.d.ts +2 -2
  16. package/dist/commands/vet-list.js +12 -5
  17. package/dist/commands/vet.d.ts +3 -3
  18. package/dist/commands/vet.js +9 -5
  19. package/dist/core/bootstrap.d.ts +1 -1
  20. package/dist/core/bootstrap.js +20 -16
  21. package/dist/core/category-mapping.d.ts +1 -1
  22. package/dist/core/category-mapping.js +104 -13
  23. package/dist/core/errors.d.ts +8 -1
  24. package/dist/core/errors.js +31 -19
  25. package/dist/core/gist-state-store.d.ts +1 -1
  26. package/dist/core/gist-state-store.js +55 -28
  27. package/dist/core/github.d.ts +1 -1
  28. package/dist/core/github.js +5 -5
  29. package/dist/core/http-cache.js +26 -22
  30. package/dist/core/issue-discovery.d.ts +6 -6
  31. package/dist/core/issue-discovery.js +279 -286
  32. package/dist/core/issue-eligibility.d.ts +2 -2
  33. package/dist/core/issue-eligibility.js +26 -21
  34. package/dist/core/issue-filtering.js +23 -15
  35. package/dist/core/issue-scoring.js +1 -1
  36. package/dist/core/issue-vetting.d.ts +2 -4
  37. package/dist/core/issue-vetting.js +65 -56
  38. package/dist/core/local-state.d.ts +1 -1
  39. package/dist/core/local-state.js +16 -14
  40. package/dist/core/repo-health.d.ts +2 -2
  41. package/dist/core/repo-health.js +46 -35
  42. package/dist/core/schemas.d.ts +17 -9
  43. package/dist/core/schemas.js +47 -19
  44. package/dist/core/search-budget.js +3 -3
  45. package/dist/core/search-phases.d.ts +6 -6
  46. package/dist/core/search-phases.js +23 -19
  47. package/dist/core/types.d.ts +9 -9
  48. package/dist/core/types.js +15 -3
  49. package/dist/core/utils.d.ts +10 -1
  50. package/dist/core/utils.js +44 -25
  51. package/dist/formatters/json.d.ts +1 -1
  52. package/dist/index.d.ts +7 -7
  53. package/dist/index.js +5 -5
  54. package/dist/scout.d.ts +30 -6
  55. package/dist/scout.js +141 -34
  56. package/package.json +7 -3
package/dist/cli.js CHANGED
@@ -2,41 +2,41 @@
2
2
  /**
3
3
  * oss-scout CLI — Find open source issues personalized to your contribution history.
4
4
  */
5
- import { Command } from 'commander';
6
- import { enableDebug } from './core/logger.js';
7
- import { getCLIVersion } from './core/utils.js';
8
- import { formatJsonSuccess, formatJsonError } from './formatters/json.js';
9
- import { errorMessage, resolveErrorCode } from './core/errors.js';
10
- import { hasLocalState, loadLocalState, saveLocalState } from './core/local-state.js';
11
- import { CONCRETE_STRATEGIES, SearchStrategySchema } from './core/schemas.js';
5
+ import { Command } from "commander";
6
+ import { enableDebug } from "./core/logger.js";
7
+ import { getCLIVersion } from "./core/utils.js";
8
+ import { formatJsonSuccess, formatJsonError } from "./formatters/json.js";
9
+ import { errorMessage, resolveErrorCode } from "./core/errors.js";
10
+ import { hasLocalState, loadLocalState, saveLocalState, } from "./core/local-state.js";
11
+ import { CONCRETE_STRATEGIES, SearchStrategySchema } from "./core/schemas.js";
12
12
  function handleCommandError(err, options) {
13
13
  if (options.json) {
14
14
  console.log(formatJsonError(errorMessage(err), resolveErrorCode(err)));
15
15
  }
16
16
  else {
17
- console.error('Error:', errorMessage(err));
17
+ console.error("Error:", errorMessage(err));
18
18
  }
19
19
  process.exit(1);
20
20
  }
21
21
  const program = new Command();
22
22
  program
23
- .name('oss-scout')
24
- .description('Find open source issues personalized to your contribution history')
23
+ .name("oss-scout")
24
+ .description("Find open source issues personalized to your contribution history")
25
25
  .version(getCLIVersion())
26
- .option('--debug', 'Enable debug output');
26
+ .option("--debug", "Enable debug output");
27
27
  // Parse --debug early so it's available in preAction hooks
28
- program.hook('preAction', (_thisCommand, _actionCommand) => {
28
+ program.hook("preAction", (_thisCommand, _actionCommand) => {
29
29
  const opts = program.opts();
30
30
  if (opts.debug)
31
31
  enableDebug();
32
32
  });
33
33
  program
34
- .command('setup')
35
- .description('Interactive first-run configuration')
36
- .option('--json', 'Output as JSON')
34
+ .command("setup")
35
+ .description("Interactive first-run configuration")
36
+ .option("--json", "Output as JSON")
37
37
  .action(async (options) => {
38
38
  try {
39
- const { runSetup } = await import('./commands/setup.js');
39
+ const { runSetup } = await import("./commands/setup.js");
40
40
  const prefs = await runSetup();
41
41
  const state = loadLocalState();
42
42
  state.preferences = prefs;
@@ -50,17 +50,21 @@ program
50
50
  }
51
51
  });
52
52
  program
53
- .command('bootstrap')
54
- .description('Import starred repos and PR history from GitHub')
55
- .option('--json', 'Output as JSON')
53
+ .command("bootstrap")
54
+ .description("Import starred repos and PR history from GitHub")
55
+ .option("--json", "Output as JSON")
56
56
  .action(async (options) => {
57
57
  try {
58
- const { bootstrapScout } = await import('./core/bootstrap.js');
59
- const { createScout } = await import('./scout.js');
60
- const { requireGitHubToken } = await import('./core/utils.js');
58
+ const { bootstrapScout } = await import("./core/bootstrap.js");
59
+ const { createScout } = await import("./scout.js");
60
+ const { requireGitHubToken } = await import("./core/utils.js");
61
61
  const token = requireGitHubToken();
62
62
  const state = loadLocalState();
63
- const scout = await createScout({ githubToken: token, persistence: 'provided', initialState: state });
63
+ const scout = await createScout({
64
+ githubToken: token,
65
+ persistence: "provided",
66
+ initialState: state,
67
+ });
64
68
  const result = await bootstrapScout(scout, token);
65
69
  saveLocalState(scout.getState());
66
70
  if (options.json) {
@@ -68,7 +72,7 @@ program
68
72
  }
69
73
  else {
70
74
  if (result.skippedDueToRateLimit) {
71
- console.log('Skipped: GitHub API rate limit too low. Try again later.');
75
+ console.log("Skipped: GitHub API rate limit too low. Try again later.");
72
76
  }
73
77
  else {
74
78
  console.log(`Imported ${result.mergedPRCount} merged PRs, ${result.closedPRCount} closed PRs, ${result.starredRepoCount} starred repos`);
@@ -81,35 +85,41 @@ program
81
85
  }
82
86
  });
83
87
  program
84
- .command('search [count]')
85
- .description('Search for contributable issues using multi-strategy discovery')
86
- .option('--json', 'Output as JSON')
87
- .option('--strategy <strategies>', `Search strategies (${CONCRETE_STRATEGIES.join(',')},all)`, 'all')
88
+ .command("search [count]")
89
+ .description("Search for contributable issues using multi-strategy discovery")
90
+ .option("--json", "Output as JSON")
91
+ .option("--strategy <strategies>", `Search strategies (${CONCRETE_STRATEGIES.join(",")},all)`, "all")
88
92
  .action(async (count, options) => {
89
93
  try {
90
94
  if (!hasLocalState()) {
91
- console.log('💡 Run `oss-scout setup` to configure your preferences for personalized search results.\n');
95
+ console.log("💡 Run `oss-scout setup` to configure your preferences for personalized search results.\n");
92
96
  }
93
- const { runSearch } = await import('./commands/search.js');
97
+ const { runSearch } = await import("./commands/search.js");
94
98
  const maxResults = count ? parseInt(count, 10) : 10;
95
99
  if (isNaN(maxResults) || maxResults < 1) {
96
- console.error('Error: count must be a positive integer');
100
+ console.error("Error: count must be a positive integer");
97
101
  process.exit(1);
98
102
  }
99
103
  const state = loadLocalState();
100
104
  if (state.mergedPRs.length === 0 &&
101
105
  state.starredRepos.length === 0 &&
102
106
  state.preferences.githubUsername) {
103
- console.log('Run `oss-scout bootstrap` to import your starred repos and PR history for better results.\n');
107
+ console.log("Run `oss-scout bootstrap` to import your starred repos and PR history for better results.\n");
104
108
  }
105
109
  // Parse --strategy option
106
- const strategyTokens = (options.strategy ?? 'all').split(',').map(s => s.trim()).filter(Boolean);
110
+ const strategyTokens = (options.strategy ?? "all")
111
+ .split(",")
112
+ .map((s) => s.trim())
113
+ .filter(Boolean);
107
114
  const strategies = [];
108
115
  for (const token of strategyTokens) {
109
116
  const parsed = SearchStrategySchema.safeParse(token);
110
117
  if (!parsed.success) {
111
- const valid = [...CONCRETE_STRATEGIES, 'all'].join(', ');
112
- console.error('Error: unknown strategy "' + token + '". Valid strategies: ' + valid);
118
+ const valid = [...CONCRETE_STRATEGIES, "all"].join(", ");
119
+ console.error('Error: unknown strategy "' +
120
+ token +
121
+ '". Valid strategies: ' +
122
+ valid);
113
123
  process.exit(1);
114
124
  }
115
125
  strategies.push(parsed.data);
@@ -122,7 +132,11 @@ program
122
132
  // Human-readable output
123
133
  console.log(`\nFound ${results.candidates.length} issue candidates:\n`);
124
134
  for (const c of results.candidates) {
125
- const icon = c.recommendation === 'approve' ? '✅' : c.recommendation === 'skip' ? '❌' : '⚠️';
135
+ const icon = c.recommendation === "approve"
136
+ ? "✅"
137
+ : c.recommendation === "skip"
138
+ ? "❌"
139
+ : "⚠️";
126
140
  console.log(` ${icon} ${c.issue.repo}#${c.issue.number} [${c.viabilityScore}/100]`);
127
141
  console.log(` ${c.issue.title}`);
128
142
  console.log(` ${c.issue.url}`);
@@ -142,33 +156,33 @@ program
142
156
  });
143
157
  // ── results command ────────────────────────────────────────────────
144
158
  const resultsCmd = program
145
- .command('results')
146
- .description('Show saved search results');
159
+ .command("results")
160
+ .description("Show saved search results");
147
161
  resultsCmd
148
- .command('show', { isDefault: true })
149
- .description('Display saved search results')
150
- .option('--json', 'Output as JSON')
162
+ .command("show", { isDefault: true })
163
+ .description("Display saved search results")
164
+ .option("--json", "Output as JSON")
151
165
  .action(async (options) => {
152
166
  try {
153
- const { runResults } = await import('./commands/results.js');
167
+ const { runResults } = await import("./commands/results.js");
154
168
  const results = await runResults(options);
155
169
  if (options.json) {
156
170
  console.log(formatJsonSuccess(results));
157
171
  }
158
172
  else {
159
173
  if (results.length === 0) {
160
- console.log('\nNo saved results. Run `oss-scout search` to find issues.\n');
174
+ console.log("\nNo saved results. Run `oss-scout search` to find issues.\n");
161
175
  return;
162
176
  }
163
177
  console.log(`\nSaved results (${results.length}):\n`);
164
- console.log(' Score Repo Issue Recommendation Title');
165
- console.log(' ───── ──────────────────────────────── ────── ────────────── ─────');
178
+ console.log(" Score Repo Issue Recommendation Title");
179
+ console.log(" ───── ──────────────────────────────── ────── ────────────── ─────");
166
180
  for (const r of results) {
167
181
  const score = String(r.viabilityScore).padStart(3);
168
182
  const repo = r.repo.padEnd(32).slice(0, 32);
169
183
  const issue = `#${r.number}`.padEnd(6);
170
184
  const rec = r.recommendation.padEnd(14);
171
- const title = r.title.length > 50 ? r.title.slice(0, 47) + '...' : r.title;
185
+ const title = r.title.length > 50 ? r.title.slice(0, 47) + "..." : r.title;
172
186
  console.log(` ${score} ${repo} ${issue} ${rec} ${title}`);
173
187
  }
174
188
  console.log();
@@ -179,18 +193,18 @@ resultsCmd
179
193
  }
180
194
  });
181
195
  resultsCmd
182
- .command('clear')
183
- .description('Clear all saved results')
184
- .option('--json', 'Output as JSON')
196
+ .command("clear")
197
+ .description("Clear all saved results")
198
+ .option("--json", "Output as JSON")
185
199
  .action(async (options) => {
186
200
  try {
187
- const { runResultsClear } = await import('./commands/results.js');
201
+ const { runResultsClear } = await import("./commands/results.js");
188
202
  await runResultsClear();
189
203
  if (options.json) {
190
204
  console.log(formatJsonSuccess({ cleared: true }));
191
205
  }
192
206
  else {
193
- console.log('Saved results cleared.');
207
+ console.log("Saved results cleared.");
194
208
  }
195
209
  }
196
210
  catch (err) {
@@ -199,17 +213,17 @@ resultsCmd
199
213
  });
200
214
  // ── config command ──────────────────────────────────────────────────
201
215
  const configCmd = program
202
- .command('config')
203
- .description('View and update preferences')
204
- .option('--json', 'Output as JSON')
216
+ .command("config")
217
+ .description("View and update preferences")
218
+ .option("--json", "Output as JSON")
205
219
  .action(async (options) => {
206
220
  try {
207
- const { runConfigShow, getConfigData } = await import('./commands/config.js');
221
+ const { runConfigShow, getConfigData } = await import("./commands/config.js");
208
222
  if (options.json) {
209
223
  console.log(formatJsonSuccess(getConfigData()));
210
224
  }
211
225
  else {
212
- runConfigShow(options);
226
+ runConfigShow();
213
227
  }
214
228
  }
215
229
  catch (err) {
@@ -217,12 +231,12 @@ const configCmd = program
217
231
  }
218
232
  });
219
233
  configCmd
220
- .command('set <key> <value>')
221
- .description('Update a single preference (e.g. config set minStars 100)')
222
- .option('--json', 'Output as JSON')
234
+ .command("set <key> <value>")
235
+ .description("Update a single preference (e.g. config set minStars 100)")
236
+ .option("--json", "Output as JSON")
223
237
  .action(async (key, value, options) => {
224
238
  try {
225
- const { runConfigSet } = await import('./commands/config.js');
239
+ const { runConfigSet } = await import("./commands/config.js");
226
240
  const updated = runConfigSet(key, value);
227
241
  if (options.json) {
228
242
  console.log(formatJsonSuccess(updated));
@@ -236,18 +250,18 @@ configCmd
236
250
  }
237
251
  });
238
252
  configCmd
239
- .command('reset')
240
- .description('Reset all preferences to defaults')
241
- .option('--json', 'Output as JSON')
253
+ .command("reset")
254
+ .description("Reset all preferences to defaults")
255
+ .option("--json", "Output as JSON")
242
256
  .action(async (options) => {
243
257
  try {
244
- const { runConfigReset } = await import('./commands/config.js');
258
+ const { runConfigReset } = await import("./commands/config.js");
245
259
  const defaults = runConfigReset();
246
260
  if (options.json) {
247
261
  console.log(formatJsonSuccess(defaults));
248
262
  }
249
263
  else {
250
- console.log('✅ Preferences reset to defaults.');
264
+ console.log("✅ Preferences reset to defaults.");
251
265
  }
252
266
  }
253
267
  catch (err) {
@@ -255,18 +269,19 @@ configCmd
255
269
  }
256
270
  });
257
271
  program
258
- .command('vet-list')
259
- .description('Re-vet all saved search results and classify their current status')
260
- .option('--prune', 'Remove unavailable issues from saved results')
261
- .option('--concurrency <n>', 'Max concurrent API requests (default: 5)', parseInt)
262
- .option('--json', 'Output as JSON')
272
+ .command("vet-list")
273
+ .description("Re-vet all saved search results and classify their current status")
274
+ .option("--prune", "Remove unavailable issues from saved results")
275
+ .option("--concurrency <n>", "Max concurrent API requests (default: 5)", parseInt)
276
+ .option("--json", "Output as JSON")
263
277
  .action(async (options) => {
264
278
  try {
265
- if (options.concurrency !== undefined && (isNaN(options.concurrency) || options.concurrency < 1)) {
266
- console.error('Error: --concurrency must be a positive integer');
279
+ if (options.concurrency !== undefined &&
280
+ (isNaN(options.concurrency) || options.concurrency < 1)) {
281
+ console.error("Error: --concurrency must be a positive integer");
267
282
  process.exit(1);
268
283
  }
269
- const { runVetList } = await import('./commands/vet-list.js');
284
+ const { runVetList } = await import("./commands/vet-list.js");
270
285
  const state = loadLocalState();
271
286
  const result = await runVetList({
272
287
  state,
@@ -278,16 +293,21 @@ program
278
293
  }
279
294
  else {
280
295
  if (result.results.length === 0) {
281
- console.log('\nNo saved results to vet. Run `oss-scout search` first.\n');
296
+ console.log("\nNo saved results to vet. Run `oss-scout search` first.\n");
282
297
  return;
283
298
  }
284
299
  console.log(`\nVet-list results (${result.summary.total}):\n`);
285
300
  for (const r of result.results) {
286
- const icon = r.status === 'still_available' ? '✅' :
287
- r.status === 'claimed' ? '🔒' :
288
- r.status === 'has_pr' ? '🔀' :
289
- r.status === 'closed' ? '🚫' : '❌';
290
- const score = r.viabilityScore != null ? ` [${r.viabilityScore}/100]` : '';
301
+ const icon = r.status === "still_available"
302
+ ? "✅"
303
+ : r.status === "claimed"
304
+ ? "🔒"
305
+ : r.status === "has_pr"
306
+ ? "🔀"
307
+ : r.status === "closed"
308
+ ? "🚫"
309
+ : "❌";
310
+ const score = r.viabilityScore != null ? ` [${r.viabilityScore}/100]` : "";
291
311
  console.log(` ${icon} ${r.repo}#${r.number} — ${r.status}${score}`);
292
312
  console.log(` ${r.title}`);
293
313
  }
@@ -302,34 +322,145 @@ program
302
322
  handleCommandError(err, options);
303
323
  }
304
324
  });
325
+ // ── skip command ───────────────────────────────────────────────────
326
+ const skipCmd = program
327
+ .command("skip")
328
+ .description("Manage the skip list — exclude issues from future searches");
329
+ skipCmd
330
+ .command("add <issue-url>")
331
+ .description("Skip an issue by URL")
332
+ .option("--json", "Output as JSON")
333
+ .action(async (issueUrl, options) => {
334
+ try {
335
+ const { runSkip } = await import("./commands/skip.js");
336
+ const state = loadLocalState();
337
+ const result = await runSkip({ issueUrl, state });
338
+ if (options.json) {
339
+ console.log(formatJsonSuccess(result));
340
+ }
341
+ else {
342
+ if (result.alreadySkipped) {
343
+ console.log("Issue already in skip list.");
344
+ }
345
+ else {
346
+ console.log(`Skipped: ${issueUrl}`);
347
+ }
348
+ }
349
+ }
350
+ catch (err) {
351
+ handleCommandError(err, options);
352
+ }
353
+ });
354
+ skipCmd
355
+ .command("list")
356
+ .description("Show all skipped issues")
357
+ .option("--json", "Output as JSON")
358
+ .action(async (options) => {
359
+ try {
360
+ const { runSkipList } = await import("./commands/skip.js");
361
+ const results = runSkipList();
362
+ if (options.json) {
363
+ console.log(formatJsonSuccess(results));
364
+ }
365
+ else {
366
+ if (results.length === 0) {
367
+ console.log("\nNo skipped issues.\n");
368
+ return;
369
+ }
370
+ console.log(`\nSkipped issues (${results.length}):\n`);
371
+ console.log(" Repo Issue Skipped Title");
372
+ console.log(" ──────────────────────────────── ────── ────────── ─────");
373
+ for (const s of results) {
374
+ const repo = (s.repo || "unknown").padEnd(32).slice(0, 32);
375
+ const issue = s.number ? `#${s.number}`.padEnd(6) : "—".padEnd(6);
376
+ const skippedDate = s.skippedAt.split("T")[0] ?? "";
377
+ const title = s.title.length > 50
378
+ ? s.title.slice(0, 47) + "..."
379
+ : s.title || s.url;
380
+ console.log(` ${repo} ${issue} ${skippedDate} ${title}`);
381
+ }
382
+ console.log();
383
+ }
384
+ }
385
+ catch (err) {
386
+ handleCommandError(err, options);
387
+ }
388
+ });
389
+ skipCmd
390
+ .command("remove <issue-url>")
391
+ .description("Remove an issue from the skip list (unskip)")
392
+ .option("--json", "Output as JSON")
393
+ .action(async (issueUrl, options) => {
394
+ try {
395
+ const { runSkipRemove } = await import("./commands/skip.js");
396
+ const result = await runSkipRemove({ issueUrl });
397
+ if (options.json) {
398
+ console.log(formatJsonSuccess(result));
399
+ }
400
+ else {
401
+ if (result.removed) {
402
+ console.log(`Removed from skip list: ${issueUrl}`);
403
+ }
404
+ else {
405
+ console.log("Issue was not in the skip list.");
406
+ }
407
+ }
408
+ }
409
+ catch (err) {
410
+ handleCommandError(err, options);
411
+ }
412
+ });
413
+ skipCmd
414
+ .command("clear")
415
+ .description("Clear all skipped issues")
416
+ .option("--json", "Output as JSON")
417
+ .action(async (options) => {
418
+ try {
419
+ const { runSkipClear } = await import("./commands/skip.js");
420
+ await runSkipClear();
421
+ if (options.json) {
422
+ console.log(formatJsonSuccess({ cleared: true }));
423
+ }
424
+ else {
425
+ console.log("Skip list cleared.");
426
+ }
427
+ }
428
+ catch (err) {
429
+ handleCommandError(err, options);
430
+ }
431
+ });
305
432
  program
306
- .command('vet <issue-url>')
307
- .description('Vet a specific GitHub issue for claimability and project health')
308
- .option('--json', 'Output as JSON')
433
+ .command("vet <issue-url>")
434
+ .description("Vet a specific GitHub issue for claimability and project health")
435
+ .option("--json", "Output as JSON")
309
436
  .action(async (issueUrl, options) => {
310
437
  try {
311
- const { runVet } = await import('./commands/vet.js');
438
+ const { runVet } = await import("./commands/vet.js");
312
439
  const state = loadLocalState();
313
440
  const result = await runVet({ issueUrl, state });
314
441
  if (options.json) {
315
442
  console.log(formatJsonSuccess(result));
316
443
  }
317
444
  else {
318
- const icon = result.recommendation === 'approve' ? '✅' : result.recommendation === 'skip' ? '❌' : '⚠️';
445
+ const icon = result.recommendation === "approve"
446
+ ? "✅"
447
+ : result.recommendation === "skip"
448
+ ? "❌"
449
+ : "⚠️";
319
450
  console.log(`\n${icon} ${result.issue.repo}#${result.issue.number}: ${result.recommendation.toUpperCase()}`);
320
451
  console.log(` ${result.issue.title}`);
321
452
  console.log(` ${result.issue.url}\n`);
322
453
  if (result.reasonsToApprove.length > 0) {
323
- console.log('Reasons to approve:');
454
+ console.log("Reasons to approve:");
324
455
  for (const r of result.reasonsToApprove)
325
456
  console.log(` + ${r}`);
326
457
  }
327
458
  if (result.reasonsToSkip.length > 0) {
328
- console.log('Reasons to skip:');
459
+ console.log("Reasons to skip:");
329
460
  for (const r of result.reasonsToSkip)
330
461
  console.log(` - ${r}`);
331
462
  }
332
- console.log(`\nProject health: ${result.projectHealth.isActive ? 'Active' : 'Inactive'}`);
463
+ console.log(`\nProject health: ${result.projectHealth.isActive ? "Active" : "Inactive"}`);
333
464
  console.log(` Last commit: ${result.projectHealth.daysSinceLastCommit} days ago`);
334
465
  console.log(` CI status: ${result.projectHealth.ciStatus}`);
335
466
  }
@@ -1,13 +1,11 @@
1
1
  /**
2
2
  * Config command — view and update oss-scout preferences.
3
3
  */
4
- import type { ScoutPreferences } from '../core/schemas.js';
4
+ import type { ScoutPreferences } from "../core/schemas.js";
5
5
  /**
6
6
  * Display current preferences in human-readable format.
7
7
  */
8
- export declare function runConfigShow(options: {
9
- json?: boolean;
10
- }): void;
8
+ export declare function runConfigShow(): void;
11
9
  /**
12
10
  * Get current preferences for JSON output.
13
11
  */