Skip to content

Commit c44eec4

Browse files
authored
Merge pull request #49 from agent-ecosystem/feat/skip-check-ids-follow-ups
New '--skip-checks' follow ups
2 parents fdf9e4e + 0635be7 commit c44eec4

3 files changed

Lines changed: 71 additions & 4 deletions

File tree

docs/reference/programmatic-api.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ Pass a second argument to configure sampling, concurrency, and thresholds:
3131
```ts
3232
import { runChecks } from 'afdocs';
3333

34+
// Run specific checks (include-list)
3435
const report = await runChecks('https://docs.example.com', {
35-
checkIds: ['llms-txt-exists', 'llms-txt-valid', 'llms-txt-size'], // include-list
36-
skipCheckIds: ['markdown-content-parity'], // exclude-list
36+
checkIds: ['llms-txt-exists', 'llms-txt-valid', 'llms-txt-size'],
3737
samplingStrategy: 'deterministic',
3838
maxLinksToTest: 20,
3939
maxConcurrency: 5,
@@ -44,7 +44,12 @@ const report = await runChecks('https://docs.example.com', {
4444
},
4545
});
4646

47-
// Or test specific pages with curated sampling:
47+
// Or run all checks except a few (exclude-list)
48+
const skipReport = await runChecks('https://docs.example.com', {
49+
skipCheckIds: ['markdown-content-parity'],
50+
});
51+
52+
// Or test specific pages with curated sampling
4853
const curatedReport = await runChecks('https://docs.example.com', {
4954
samplingStrategy: 'curated',
5055
curatedPages: [

src/runner.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,17 @@ export async function runChecks(
7272
const checkIds = options?.checkIds;
7373
const skipCheckIds = options?.skipCheckIds ?? [];
7474

75+
// Warn about overlapping checkIds and skipCheckIds
76+
if (checkIds && checkIds.length > 0 && skipCheckIds.length > 0) {
77+
const overlap = skipCheckIds.filter((id) => checkIds.includes(id));
78+
if (overlap.length > 0) {
79+
console.warn(
80+
`Warning: ${overlap.join(', ')} listed in both --checks and --skip-checks. ` +
81+
`These checks will be skipped.`,
82+
);
83+
}
84+
}
85+
7586
const results: CheckResult[] = [];
7687

7788
for (const check of allChecks) {

test/unit/runner.test.ts

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { describe, it, expect, beforeAll } from 'vitest';
1+
import { describe, it, expect, beforeAll, vi } from 'vitest';
22
import { http, HttpResponse } from 'msw';
33
import { setupServer } from 'msw/node';
44
import { createContext, normalizeUrl, runChecks } from '../../src/runner.js';
@@ -296,6 +296,7 @@ describe('runner', () => {
296296
});
297297

298298
it('skips checks listed in skipCheckIds without running them', async () => {
299+
const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
299300
server.use(
300301
http.get('http://skip-ids.local/llms.txt', () => new HttpResponse(null, { status: 404 })),
301302
http.get(
@@ -326,9 +327,11 @@ describe('runner', () => {
326327
expect(size).toBeDefined();
327328
expect(size?.status).toBe('skip');
328329
expect(size?.message).toContain('dependency');
330+
warnSpy.mockRestore();
329331
});
330332

331333
it('skipCheckIds does not cascade-skip dependent checks', async () => {
334+
const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
332335
const content = `# Test\n\n> Summary.\n\n## Links\n\n- [A](http://skip-dep.local/a): A\n`;
333336
server.use(
334337
http.get('http://skip-dep.local/llms.txt', () => HttpResponse.text(content)),
@@ -355,6 +358,54 @@ describe('runner', () => {
355358
const valid = report.results.find((r) => r.id === 'llms-txt-valid');
356359
expect(valid).toBeDefined();
357360
expect(valid?.message).not.toContain('dependency');
361+
warnSpy.mockRestore();
362+
});
363+
364+
it('warns when checkIds and skipCheckIds overlap', async () => {
365+
const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
366+
367+
server.use(
368+
http.get('http://overlap.local/llms.txt', () => new HttpResponse(null, { status: 404 })),
369+
http.get('http://overlap.local/docs/llms.txt', () => new HttpResponse(null, { status: 404 })),
370+
);
371+
372+
const report = await runChecks('http://overlap.local', {
373+
checkIds: ['llms-txt-exists', 'llms-txt-valid'],
374+
skipCheckIds: ['llms-txt-valid'],
375+
requestDelay: 0,
376+
});
377+
378+
expect(warnSpy).toHaveBeenCalledOnce();
379+
expect(warnSpy.mock.calls[0][0]).toContain('llms-txt-valid');
380+
expect(warnSpy.mock.calls[0][0]).toContain('--checks');
381+
expect(warnSpy.mock.calls[0][0]).toContain('--skip-checks');
382+
383+
// The overlapping check should still be skipped (skip wins)
384+
const skipped = report.results.find((r) => r.id === 'llms-txt-valid');
385+
expect(skipped?.status).toBe('skip');
386+
387+
warnSpy.mockRestore();
388+
});
389+
390+
it('does not warn when checkIds and skipCheckIds do not overlap', async () => {
391+
const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
392+
393+
server.use(
394+
http.get('http://no-overlap.local/llms.txt', () => new HttpResponse(null, { status: 404 })),
395+
http.get(
396+
'http://no-overlap.local/docs/llms.txt',
397+
() => new HttpResponse(null, { status: 404 }),
398+
),
399+
);
400+
401+
await runChecks('http://no-overlap.local', {
402+
checkIds: ['llms-txt-exists', 'llms-txt-valid'],
403+
skipCheckIds: ['llms-txt-size'],
404+
requestDelay: 0,
405+
});
406+
407+
expect(warnSpy).not.toHaveBeenCalled();
408+
warnSpy.mockRestore();
358409
});
359410

360411
it('includes timestamp and url in report', async () => {

0 commit comments

Comments
 (0)