From cfc410ba61aef9a93b6e7994420ae8e566adcce4 Mon Sep 17 00:00:00 2001 From: "warp-agent-staging[bot]" <240773466+warp-agent-staging[bot]@users.noreply.github.com> Date: Fri, 30 Oct 2026 18:32:12 +0000 Subject: [PATCH 1/2] AFDocs fixes: preserve file-tree examples and audit diagnostics Co-Authored-By: Oz --- .agents/skills/afdocs-audit/SKILL.md | 5 +++ .../afdocs-audit/scripts/afdocs_audit.mjs | 24 ++++++++++- .../scripts/afdocs_audit.test.mjs | 42 +++++++++++++++++++ src/integrations/docs-markdown-integration.js | 5 +++ .../docs-markdown-integration.test.js | 21 ++++++++++ 5 files changed, 95 insertions(+), 2 deletions(-) diff --git a/.agents/skills/afdocs-audit/SKILL.md b/.agents/skills/afdocs-audit/SKILL.md index 1d87a80e9..af720f4a9 100644 --- a/.agents/skills/afdocs-audit/SKILL.md +++ b/.agents/skills/afdocs-audit/SKILL.md @@ -52,6 +52,7 @@ Each issue includes: - `status` — `fail` or `warn` - `message` — Human-readable description - `fix` — Suggested fix from the AFDocs spec +- `details` — Original check diagnostics, including affected URLs and fetch errors when the CLI supplies them; also retained for every check in `all_results` ### v0.6 compatibility checks and reliability @@ -76,6 +77,10 @@ effect records this condition. The `dynamic-content-rendered-statically` interac effect is recorded when multiple size, serialization, parity, or pagination signals co-occur; it is diagnostic and does not add another score penalty. +Reported fetch errors, rate limiting, or discovery warnings also make the scan partial, +even when bot protection passes. Exclude these results from regression comparisons and +baselines, and inspect the retained check details before attempting remediation. + ### Known exceptions Before reporting, cross-reference every issue against the known exceptions in `references/known-exceptions.md`. Classify each issue into exactly one bucket: diff --git a/.agents/skills/afdocs-audit/scripts/afdocs_audit.mjs b/.agents/skills/afdocs-audit/scripts/afdocs_audit.mjs index 91aec12fe..466152d5c 100755 --- a/.agents/skills/afdocs-audit/scripts/afdocs_audit.mjs +++ b/.agents/skills/afdocs-audit/scripts/afdocs_audit.mjs @@ -663,10 +663,23 @@ function scanReliability(results) { message: 'Sustained automated fetching was interrupted, so multi-page findings may not represent the complete site.', }; } + const interruptedChecks = results.filter((result) => + result.details?.fetchErrors > 0 || + result.details?.rateLimited > 0 || + result.details?.discoveryWarnings?.length > 0 + ); + if (interruptedChecks.length > 0) { + return { + status: 'partial', + reason: 'fetch-or-discovery-errors', + affected_checks: interruptedChecks.map((result) => result.id), + message: 'Fetch failures, rate limiting, or discovery warnings interrupted this scan; exclude it from regression comparisons and baselines.', + }; + } return { status: 'complete', reason: null, - message: 'No bot-protection interference was observed during this scan.', + message: 'No bot-protection interference, fetch failures, rate limiting, or discovery warnings were reported during this scan.', }; } @@ -716,6 +729,7 @@ export function buildReport(raw, supplementalResults = []) { status: r.status, message: r.message, fix: r.details?.fix || r.fix || null, + details: r.details ?? null, })); return { @@ -738,7 +752,13 @@ export function buildReport(raw, supplementalResults = []) { ]) ), issues, - all_results: results.map((r) => ({ id: r.id, category: r.category, status: r.status, message: r.message })), + all_results: results.map((r) => ({ + id: r.id, + category: r.category, + status: r.status, + message: r.message, + details: r.details ?? null, + })), scan_reliability: scanReliability(results), interaction_effects: interactionEffects(results), }; diff --git a/.agents/skills/afdocs-audit/scripts/afdocs_audit.test.mjs b/.agents/skills/afdocs-audit/scripts/afdocs_audit.test.mjs index a857576b2..1fca7cf0d 100644 --- a/.agents/skills/afdocs-audit/scripts/afdocs_audit.test.mjs +++ b/.agents/skills/afdocs-audit/scripts/afdocs_audit.test.mjs @@ -100,6 +100,48 @@ test('uses the native CLI score after afdocs supplies every v0.6 check', () => { assert.equal(report.score_method, 'native afdocs CLI score'); }); +test('retains page-level diagnostics and excludes fetch-interrupted scans from complete baselines', () => { + const result = { + id: 'markdown-content-parity', + category: 'observability', + status: 'pass', + message: 'Compared available pages; one failed to fetch', + details: { + fetchErrors: 1, + rateLimited: 0, + pageResults: [{ url: 'https://docs.example.com/page/', status: 'pass' }], + }, + }; + const report = buildReport({ score: 90, results: [result] }); + + assert.equal(report.score, 90); + assert.equal(report.scan_reliability.status, 'partial'); + assert.deepEqual(report.scan_reliability.affected_checks, [result.id]); + assert.deepEqual(report.all_results[0].details, result.details); + + const warning = buildReport({ score: 90, results: [{ ...result, status: 'warn' }] }); + assert.deepEqual(warning.issues[0].details, result.details); +}); + +test('treats rate limiting and discovery warnings as partial without interpreting intentional 404 tests as fetch errors', () => { + for (const details of [{ rateLimited: 1 }, { discoveryWarnings: ['Sitemap fetch failed'] }]) { + const report = buildReport({ score: 90, results: [{ ...legacyResult, details }] }); + assert.equal(report.scan_reliability.status, 'partial'); + } + + const report = buildReport({ + score: 90, + results: [{ + ...legacyResult, + details: { + fetchErrors: 0, rateLimited: 0, discoveryWarnings: [], + pageResults: [{ url: 'https://docs.example.com/nonexistent/', status: 404 }], + }, + }], + }); + assert.equal(report.scan_reliability.status, 'complete'); +}); + test('treats a valid Link-header continuation as visible at the start of the response', async () => { const headers = { link: '; rel="next"' }; assert.deepEqual(extractContinuation('First page', headers), [ diff --git a/src/integrations/docs-markdown-integration.js b/src/integrations/docs-markdown-integration.js index ea774f588..97ae89d67 100644 --- a/src/integrations/docs-markdown-integration.js +++ b/src/integrations/docs-markdown-integration.js @@ -222,6 +222,11 @@ function normalizeTabPanels(root) { } function sanitizeRoot(root) { + // Starlight excludes file trees from search, but their examples belong in Markdown. + for (const tree of root.querySelectorAll('starlight-file-tree')) { + tree.removeAttribute('data-pagefind-ignore'); + } + for (const selector of [ 'script', 'style', diff --git a/src/integrations/docs-markdown-integration.test.js b/src/integrations/docs-markdown-integration.test.js index abe5f39d3..9b0a183af 100644 --- a/src/integrations/docs-markdown-integration.test.js +++ b/src/integrations/docs-markdown-integration.test.js @@ -181,6 +181,27 @@ test('includes inert agent-only templates in generated Markdown', () => { assert.doesNotMatch(markdown, /Search-only chrome\./); }); +test('preserves search-excluded file trees, directory nesting, and file comments', () => { + const html = createPage(`

Example project structure:

+ +
  • + Directoryproject/ +
    • + api/ +
      • AGENTS.md API-specific rules
      +
    • +
    • AGENTS.md Project-wide rules
    +
+
+

Search-only chrome.

Following guidance.

`); + const markdown = convertHtmlToMarkdown(html); + + assert.match(markdown, /- {3}project\/[\s\S]*\n {4}- {3}api\/[\s\S]*\n {8}- {3}AGENTS\.md API-specific rules/); + assert.match(markdown, /\n {4}- {3}AGENTS\.md Project-wide rules/); + assert.match(markdown, /Following guidance\./); + assert.doesNotMatch(markdown, /Directory|Search-only chrome|starlight-file-tree|
{ const html = createPage(`
From 2e7d6b9eb6bd230e9e1b6743256905939102f849 Mon Sep 17 00:00:00 2001 From: "warp-agent-staging[bot]" <240773466+warp-agent-staging[bot]@users.noreply.github.com> Date: Fri, 30 Oct 2026 20:28:33 +0000 Subject: [PATCH 2/2] ci: run AFDocs audit regression tests Co-Authored-By: Oz --- .github/workflows/ci.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1f329f165..ddca77de7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -132,6 +132,9 @@ jobs: - name: Test Markdown serialization run: npm run test:docs-markdown + - name: Test AFDocs audit + run: node --test .agents/skills/afdocs-audit/scripts/afdocs_audit.test.mjs + - name: Test tracking redirect middleware run: npm run test:tracking-redirect