@forkpoint/agent-lighthouse-core 0.2.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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/constants.ts","../src/logger.ts","../src/fetcher.ts","../src/url-utils.ts","../src/parser.ts","../src/schemas.ts","../src/audit.ts","../src/audits/content-discoverability/llms-txt-exists.ts","../src/audits/content-discoverability/llms-txt-blockquote.ts","../src/audits/content-discoverability/llms-txt-sections.ts","../src/audits/content-discoverability/llms-txt-link-descriptions.ts","../src/audits/content-discoverability/llms-txt-links-valid.ts","../src/audits/content-discoverability/llms-full-txt.ts","../src/audits/content-discoverability/sitemap-exists.ts","../src/audits/content-discoverability/sitemap-key-pages.ts","../src/audits/content-discoverability/sitemap-absolute-urls.ts","../src/audits/content-discoverability/sitemap-lastmod.ts","../src/audits/content-discoverability/rss-feed.ts","../src/audits/content-discoverability/rss-feed-content.ts","../src/audits/content-discoverability/no-noindex.ts","../src/audits/content-discoverability/no-nofollow.ts","../src/audits/content-discoverability/internal-linking.ts","../src/audits/content-discoverability/no-redirect-chains.ts","../src/audits/content-discoverability/canonical-links.ts","../src/audits/content-discoverability/mobile-friendly.ts","../src/audits/content-discoverability/fast-page-load.ts","../src/audits/content-discoverability/no-broken-links.ts","../src/audits/content-discoverability/navigation-json.ts","../src/audits/content-discoverability/no-orphan-pages.ts","../src/audits/content-discoverability/commerce-links.ts","../src/audits/crawler-permissions/_robots-txt-helpers.ts","../src/audits/crawler-permissions/_crawler-bot-audit.ts","../src/audits/crawler-permissions/gptbot.ts","../src/audits/crawler-permissions/google-extended.ts","../src/audits/crawler-permissions/anthropic.ts","../src/audits/crawler-permissions/perplexitybot.ts","../src/audits/crawler-permissions/applebot-extended.ts","../src/audits/crawler-permissions/ccbot.ts","../src/audits/crawler-permissions/meta-external-agent.ts","../src/audits/crawler-permissions/amazonbot.ts","../src/audits/crawler-permissions/bytespider.ts","../src/audits/crawler-permissions/cohere-ai.ts","../src/audits/crawler-permissions/youbot.ts","../src/audits/crawler-permissions/diffbot.ts","../src/audits/crawler-permissions/ai2bot.ts","../src/audits/crawler-permissions/chatgpt-user.ts","../src/audits/crawler-permissions/claude-user.ts","../src/audits/crawler-permissions/oai-searchbot.ts","../src/audits/crawler-permissions/meta-external-fetcher.ts","../src/audits/crawler-permissions/bravebot.ts","../src/audits/crawler-permissions/duckassistbot.ts","../src/audits/crawler-permissions/mistralai-user.ts","../src/audits/crawler-permissions/claude-searchbot.ts","../src/audits/crawler-permissions/no-blanket-block.ts","../src/audits/crawler-permissions/sensitive-paths.ts","../src/audits/crawler-permissions/crawl-delay.ts","../src/audits/crawler-permissions/meta-robots-not-blocking.ts","../src/audits/crawler-permissions/no-bot-detection.ts","../src/audits/structured-data/json-ld-present.ts","../src/audits/structured-data/schema-validation.ts","../src/audits/structured-data/organization-schema.ts","../src/audits/structured-data/website-search-action.ts","../src/audits/structured-data/breadcrumb-schema.ts","../src/audits/structured-data/article-schema.ts","../src/audits/structured-data/faqpage-schema.ts","../src/audits/structured-data/service-product-schema.ts","../src/audits/structured-data/speakable-schema.ts","../src/audits/structured-data/potential-action.ts","../src/audits/structured-data/howto-schema.ts","../src/audits/structured-data/local-business-schema.ts","../src/audits/structured-data/review-schema.ts","../src/audits/structured-data/offer-schema.ts","../src/audits/structured-data/author-schema.ts","../src/audits/structured-data/action-schema.ts","../src/audits/structured-data/product-identifiers.ts","../src/audits/structured-data/product-details.ts","../src/audits/structured-data/product-reviews.ts","../src/audits/meta-tags/meta-description.ts","../src/audits/meta-tags/meta-author.ts","../src/audits/meta-tags/canonical-url.ts","../src/audits/meta-tags/language-attribute.ts","../src/audits/meta-tags/unique-meta.ts","../src/audits/meta-tags/core-open-graph.ts","../src/audits/meta-tags/og-type.ts","../src/audits/meta-tags/og-site-name.ts","../src/audits/meta-tags/og-image-alt.ts","../src/audits/meta-tags/twitter-card.ts","../src/audits/meta-tags/llms-txt-link.ts","../src/audits/meta-tags/llms-full-txt-link.ts","../src/audits/meta-tags/ai-content-declaration.ts","../src/audits/meta-tags/ai-instructions.ts","../src/audits/meta-tags/markdown-alternate.ts","../src/audits/meta-tags/rss-feed-link.ts","../src/audits/meta-tags/mcp-discovery-link.ts","../src/audits/meta-tags/openapi-link.ts","../src/audits/meta-tags/ai-catalog-link.ts","../src/audits/meta-tags/meta-robots.ts","../src/audits/agent-tools/openapi-exists.ts","../src/audits/agent-tools/openapi-endpoints.ts","../src/audits/agent-tools/openapi-operation-ids.ts","../src/audits/agent-tools/openapi-ai-instructions.ts","../src/audits/agent-tools/openapi-servers.ts","../src/audits/agent-tools/openapi-schemas.ts","../src/audits/agent-tools/ai-catalog-exists.ts","../src/audits/agent-tools/ai-catalog-metadata.ts","../src/audits/agent-tools/ai-catalog-urls.ts","../src/audits/agent-tools/agents-json.ts","../src/audits/agent-tools/ai-plugin-json.ts","../src/audits/agent-tools/mcp-discovery.ts","../src/audits/agent-tools/mcp-endpoint.ts","../src/audits/agent-tools/mcp-capabilities.ts","../src/audits/agent-tools/contact-form.ts","../src/audits/agent-tools/search-endpoint.ts","../src/audits/agent-tools/data-action-ctas.ts","../src/audits/agent-tools/no-blocking-captcha.ts","../src/audits/agent-tools/forms-no-js.ts","../src/audits/agent-tools/webmcp-manifest.ts","../src/audits/agent-tools/webmcp-declarative-forms.ts","../src/audits/agent-tools/webmcp-input-quality.ts","../src/audits/agent-tools/webmcp-tool-naming.ts","../src/audits/agent-tools/webmcp-tool-annotations.ts","../src/audits/agent-tools/webmcp-action-coverage.ts","../src/audits/semantic-html/single-h1.ts","../src/audits/semantic-html/sequential-headings.ts","../src/audits/semantic-html/main-element.ts","../src/audits/semantic-html/article-element.ts","../src/audits/semantic-html/header-footer.ts","../src/audits/semantic-html/aside-element.ts","../src/audits/semantic-html/section-headings.ts","../src/audits/semantic-html/semantic-lists.ts","../src/audits/semantic-html/data-tables.ts","../src/audits/semantic-html/code-language.ts","../src/audits/semantic-html/time-element.ts","../src/audits/semantic-html/address-element.ts","../src/audits/semantic-html/definition-elements.ts","../src/audits/semantic-html/content-depth.ts","../src/audits/semantic-html/image-alt-text.ts","../src/audits/semantic-html/decorative-images.ts","../src/audits/semantic-html/figure-figcaption.ts","../src/audits/accessibility/skip-nav.ts","../src/audits/accessibility/aria-landmarks.ts","../src/audits/accessibility/nav-aria-label.ts","../src/audits/accessibility/form-error-messages.ts","../src/audits/accessibility/_a11y.ts","../src/audits/technical-readiness/https-enabled.ts","../src/audits/technical-readiness/hsts-header.ts","../src/audits/technical-readiness/csp-header.ts","../src/audits/technical-readiness/content-type-options.ts","../src/audits/technical-readiness/referrer-policy.ts","../src/audits/technical-readiness/permissions-policy.ts","../src/audits/technical-readiness/security-txt.ts","../src/audits/technical-readiness/cors-ai-files.ts","../src/audits/technical-readiness/cors-api-routes.ts","../src/audits/technical-readiness/correct-content-types.ts","../src/audits/technical-readiness/cache-headers.ts","../src/audits/technical-readiness/fast-response-time.ts","../src/audits/technical-readiness/server-rendered.ts","../src/audits/technical-readiness/no-render-blocking.ts","../src/audits/technical-readiness/image-dimensions.ts","../src/audits/technical-readiness/lcp-not-lazy.ts","../src/audits/technical-readiness/preconnect-hints.ts","../src/audits/technical-readiness/no-broken-ai-endpoints.ts","../src/audits/technical-readiness/privacy-policy.ts","../src/audits/technical-readiness/terms-of-service.ts","../src/audits/technical-readiness/framework-detection.ts","../src/audits/answer-engine/faq-sections.ts","../src/audits/answer-engine/question-headings.ts","../src/audits/answer-engine/dates-on-content.ts","../src/audits/answer-engine/first-paragraph-answers.ts","../src/audits/answer-engine/direct-definitions.ts","../src/audits/answer-engine/comparison-tables.ts","../src/audits/answer-engine/numbered-steps.ts","../src/audits/answer-engine/specific-numbers.ts","../src/audits/answer-engine/content-without-clickthrough.ts","../src/audits/answer-engine/last-updated-indicator.ts","../src/audits/answer-engine/meta-description-aeo.ts","../src/audits/generative-engine/named-author.ts","../src/audits/generative-engine/author-same-as.ts","../src/audits/generative-engine/author-page.ts","../src/audits/generative-engine/about-credentials.ts","../src/audits/generative-engine/external-citations.ts","../src/audits/generative-engine/brand-name.ts","../src/audits/generative-engine/trust-signals.ts","../src/audits/generative-engine/review-signals.ts","../src/audits/generative-engine/publication-date.ts","../src/audits/generative-engine/last-modified-schema.ts","../src/audits/generative-engine/internal-cross-linking.ts","../src/audits/generative-engine/pagination-links.ts","../src/audits/generative-engine/unique-data.ts","../src/audits/generative-engine/blockquote-usage.ts","../src/audits/generative-engine/descriptive-urls.ts","../src/audit-config.ts","../src/audit-runner.ts","../src/audits/accessibility/runner.ts","../src/audits/accessibility/engine/standards.ts","../src/audits/accessibility/engine/core.ts","../src/audits/accessibility/engine/dom.ts","../src/audits/accessibility/engine/table.ts","../src/audits/accessibility/engine/text.ts","../src/audits/accessibility/engine/stdhelpers.ts","../src/audits/accessibility/engine/aria.ts","../src/audits/accessibility/engine/checks.ts","../src/audits/accessibility/engine/rules.ts","../src/product-fields.ts","../src/summary.ts","../src/waf-detector.ts","../src/orchestrator.ts","../src/scorer.ts","../src/types.ts","../src/presets.ts","../src/config-loader.ts"],"sourcesContent":["export { runScan } from './orchestrator';\nexport { createFetcher, isSafeUrl } from './fetcher';\nexport type { FetchResult, FetchOptions } from './fetcher';\nexport type { CheckContext, CheckFn, PageContext } from './check-context';\nexport { Audit } from './audit';\nexport { runAudits } from './audit-runner';\nexport { defaultConfig } from './audit-config';\nexport type { ScanConfig, CategoryConfig, AuditRegistration } from './audit-config';\nexport type { AuditRunResult } from './audit-runner';\nexport {\n parseHtml,\n extractJsonLd,\n flattenJsonLd,\n extractMarkdownLinks,\n extractMetaTags,\n extractHeadLinks,\n extractHeadings,\n extractImages,\n extractForms,\n extractInternalLinks,\n extractNavLinks,\n extractScripts,\n extractStylesheetUrls,\n getMainContentText,\n getWordCount,\n detectPageType,\n} from './parser';\nexport {\n calculateCategoryScore,\n buildCategoryResult,\n calculateOverallScore,\n} from './scorer';\nexport { extractProductFieldVerification } from './product-fields';\n\n// Types & Schemas\nexport * from './types';\nexport * from './constants';\nexport * from './schemas';\nexport * from './url-utils';\nexport * from './presets';\nexport * from './config-loader';\nexport { detectWafProtection } from './waf-detector';\nexport { logger } from './logger';\n\n","import type { ScoreTier } from './types';\n\n// ── Scan Limits ────────────────────────────────────────────────\n\nexport const DEFAULT_SCAN_LIMIT = 5;\nexport const MAX_PAGES_PER_SCAN = 6; // 1 homepage + 5 internal\nexport const REQUEST_TIMEOUT_MS = 10_000;\nexport const SCAN_TIMEOUT_MS = 60_000;\nexport const MAX_RESPONSE_BODY_BYTES = 5 * 1024 * 1024; // 5MB\nexport const MAX_CONCURRENT_REQUESTS = 10;\n\n// ── Scanner Identity ───────────────────────────────────────────\n\nexport const SCANNER_USER_AGENT =\n 'AgentLighthouse/1.0 (+https://github.com/ForkPoint/agent-lighthouse)';\n\n// ── Coverage tags ──────────────────────────────────────────────\n\nexport const TAG_SKIPPED_PAGE_TYPE = 'skipped:page-type';\nexport const TAG_SCAN_ERROR = 'scan-error';\n\n// ── Scoring ────────────────────────────────────────────────────\n\nexport const CATEGORY_WEIGHTS: Record<string, number> = {\n 'content-discoverability': 0.15,\n 'crawler-permissions': 0.08,\n 'structured-data': 0.12,\n 'meta-tags': 0.08,\n 'agent-tools': 0.18,\n 'semantic-html': 0.08,\n accessibility: 0.07,\n 'technical-readiness': 0.09,\n 'answer-engine': 0.07,\n 'generative-engine': 0.08,\n};\n\nexport const CATEGORY_NAMES: Record<string, string> = {\n 'content-discoverability': 'Content Discoverability',\n 'crawler-permissions': 'AI Crawler Permissions',\n 'structured-data': 'Structured Data & Schema Markup',\n 'meta-tags': 'Meta Tags & AI Head Elements',\n 'agent-tools': 'AI Agent Tools & Action Surfaces',\n 'semantic-html': 'Semantic HTML & Content Structure',\n accessibility: 'Accessibility & Agent Interaction',\n 'technical-readiness': 'Technical Readiness & Security',\n 'answer-engine': 'Answer Engine Optimization',\n 'generative-engine': 'Generative Engine Optimization',\n};\n\nexport const READINESS_WEIGHTS = {\n commerce: 0.4,\n content: 0.25,\n botAccessibility: 0.2,\n technical: 0.15,\n} as const;\n\nexport function getScoreTier(score: number): ScoreTier {\n if (score >= 90) return 'agent-ready';\n if (score >= 70) return 'partially-ready';\n if (score >= 50) return 'needs-work';\n return 'not-ready';\n}\n\nexport const SCORE_TIER_LABELS: Record<ScoreTier, string> = {\n 'agent-ready': 'Agent Ready',\n 'partially-ready': 'Partially Ready',\n 'needs-work': 'Needs Work',\n 'not-ready': 'Not Ready',\n};\n\nexport function getTierLabel(tier: string | null): string {\n if (tier && tier in SCORE_TIER_LABELS) {\n return SCORE_TIER_LABELS[tier as ScoreTier];\n }\n return 'N/A';\n}\n\nexport function getTierColor(tier: string | null): string {\n switch (tier) {\n case 'agent-ready':\n return '#10b981';\n case 'partially-ready':\n return '#3b82f6';\n case 'needs-work':\n return '#f59e0b';\n case 'not-ready':\n return '#ef4444';\n default:\n return '#64748b';\n }\n}\n","export type LogLevel = 'silent' | 'error' | 'warn' | 'info' | 'debug';\n\nclass Logger {\n public level: LogLevel = (process.env.LOG_LEVEL as LogLevel) || 'info';\n\n private shouldLog(targetLevel: LogLevel): boolean {\n if (this.level === 'silent') return false;\n const levels: LogLevel[] = ['debug', 'info', 'warn', 'error'];\n const currentIdx = levels.indexOf(this.level);\n const targetIdx = levels.indexOf(targetLevel);\n return targetIdx >= currentIdx;\n }\n\n debug(msg: string | Record<string, unknown>, ...args: unknown[]) {\n if (this.shouldLog('debug')) {\n console.debug(typeof msg === 'string' ? `[DEBUG] ${msg}` : msg, ...args);\n }\n }\n\n info(msg: string | Record<string, unknown>, ...args: unknown[]) {\n if (this.shouldLog('info')) {\n console.info(typeof msg === 'string' ? `[INFO] ${msg}` : msg, ...args);\n }\n }\n\n warn(msg: string | Record<string, unknown>, ...args: unknown[]) {\n if (this.shouldLog('warn')) {\n console.warn(typeof msg === 'string' ? `[WARN] ${msg}` : msg, ...args);\n }\n }\n\n error(msg: string | Record<string, unknown>, ...args: unknown[]) {\n if (this.shouldLog('error')) {\n console.error(typeof msg === 'string' ? `[ERROR] ${msg}` : msg, ...args);\n }\n }\n}\n\nexport const logger = new Logger();\nexport default logger;\n","import { request, Agent, interceptors } from 'undici';\nimport dns from 'node:dns/promises';\nimport {\n SCANNER_USER_AGENT,\n REQUEST_TIMEOUT_MS,\n MAX_RESPONSE_BODY_BYTES,\n} from './constants';\nimport { isPrivateIp } from './url-utils';\nimport { logger } from './logger';\n\nconst redirectAgent = new Agent().compose(interceptors.redirect({ maxRedirections: 5 }));\n\nexport interface FetchOptions {\n url: string;\n timeout?: number;\n followRedirects?: boolean;\n acceptHeader?: string;\n method?: 'GET' | 'POST' | 'OPTIONS' | 'HEAD';\n body?: string;\n contentType?: string;\n /** External abort (e.g. the per-scan deadline). Combined with the per-request timeout. */\n signal?: AbortSignal;\n}\n\nexport interface FetchResult {\n url: string;\n finalUrl: string;\n status: number;\n headers: Record<string, string>;\n body: string;\n ttfbMs: number;\n totalMs: number;\n contentType: string;\n contentLength: number;\n error?: string;\n}\n\n/**\n * Split HTTP basic-auth credentials out of a URL's userinfo (`user:pass@host`)\n * into an `Authorization: Basic` header, returning a credential-free URL.\n *\n * undici (like the WHATWG `fetch` spec) does NOT turn URL userinfo into an auth\n * header — it silently drops it, so auth-gated staging targets return 401 and we\n * end up scanning login/error pages. We convert it explicitly. Returning a\n * cleaned URL also keeps credentials out of logs and the stored FetchResult.\n *\n * The `@` fast-path avoids re-serializing the URL in the common (no-credentials)\n * case, which would otherwise normalize it (e.g. append a trailing slash).\n */\nexport function splitCredentials(rawUrl: string): { url: string; authHeader?: string } {\n if (!rawUrl.includes('@')) return { url: rawUrl };\n try {\n const parsed = new URL(rawUrl);\n if (!parsed.username && !parsed.password) return { url: rawUrl };\n // Basic auth is base64 of the *decoded* user:pass (userinfo is percent-encoded).\n const raw = `${decodeURIComponent(parsed.username)}:${decodeURIComponent(parsed.password)}`;\n const authHeader = `Basic ${Buffer.from(raw).toString('base64')}`;\n parsed.username = '';\n parsed.password = '';\n return { url: parsed.href, authHeader };\n } catch {\n // Malformed URL — let request() surface the error.\n return { url: rawUrl };\n }\n}\n\n/**\n * Extract a stable error code from a thrown value. undici surfaces the real\n * reason for a `TypeError: fetch failed` / generic error under `err.cause.code`\n * (e.g. ENOTFOUND, ECONNREFUSED, UND_ERR_CONNECT_TIMEOUT, CERT_HAS_EXPIRED);\n * without it the logs just say \"fetch failed\" and are undiagnosable.\n */\nfunction errorCode(err: unknown): string | undefined {\n if (typeof err !== 'object' || err === null) return undefined;\n const e = err as { code?: unknown; cause?: { code?: unknown } };\n const code = e.cause?.code ?? e.code;\n return typeof code === 'string' ? code : undefined;\n}\n\n/**\n * Validates that a URL is safe to fetch (http/https scheme, non-private IP).\n * Use before fetching any URL extracted from scanned site content.\n */\nexport async function isSafeUrl(url: string): Promise<boolean> {\n try {\n const parsed = new URL(url);\n if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') return false;\n const hostname = parsed.hostname;\n if (hostname === 'localhost' || hostname === '127.0.0.1' || hostname === '::1') return false;\n if (isPrivateIp(hostname)) return false;\n const { address } = await dns.lookup(hostname);\n return !isPrivateIp(address);\n } catch {\n return false;\n }\n}\n\nexport function createFetcher() {\n async function fetch(options: FetchOptions): Promise<FetchResult> {\n const {\n url,\n timeout = REQUEST_TIMEOUT_MS,\n acceptHeader = '*/*',\n method = 'GET',\n body: requestBody,\n contentType,\n signal: externalSignal,\n } = options;\n\n // Per-request timeout, plus the caller's deadline if supplied — whichever\n // fires first aborts the request.\n const timeoutSignal = AbortSignal.timeout(timeout);\n const signal = externalSignal\n ? AbortSignal.any([timeoutSignal, externalSignal])\n : timeoutSignal;\n\n // Pull any `user:pass@` out of the URL into an Authorization header, and use\n // the credential-free URL for the request, logs, and returned result.\n const { url: targetUrl, authHeader } = splitCredentials(url);\n\n const start = performance.now();\n let ttfbMs = 0;\n\n try {\n const reqHeaders: Record<string, string> = {\n 'User-Agent': SCANNER_USER_AGENT,\n Accept: acceptHeader,\n };\n\n if (authHeader) {\n reqHeaders['Authorization'] = authHeader;\n }\n\n if (method === 'POST' && contentType) {\n reqHeaders['Content-Type'] = contentType;\n }\n\n logger.debug({ url: targetUrl, method }, `[fetcher] Starting fetch: ${method} ${targetUrl}`);\n\n const response = await request(targetUrl, {\n method,\n headers: reqHeaders,\n body: requestBody,\n signal,\n dispatcher: redirectAgent,\n });\n\n ttfbMs = performance.now() - start;\n\n let body = '';\n if (method !== 'OPTIONS') {\n body = await response.body.text();\n } else {\n // For OPTIONS requests, consume and discard the body\n await response.body.dump();\n }\n const totalMs = performance.now() - start;\n\n logger.debug(\n { url: targetUrl, status: response.statusCode, totalMs: Math.round(totalMs) },\n `[fetcher] Fetch complete: ${targetUrl} (${response.statusCode}) in ${Math.round(totalMs)}ms`,\n );\n\n const truncatedBody =\n body.length > MAX_RESPONSE_BODY_BYTES ? body.slice(0, MAX_RESPONSE_BODY_BYTES) : body;\n\n const headers: Record<string, string> = {};\n for (const [key, value] of Object.entries(response.headers)) {\n if (typeof value === 'string') {\n headers[key.toLowerCase()] = value;\n }\n }\n\n return {\n url: targetUrl,\n finalUrl: targetUrl, // undici doesn't expose final URL after redirects easily\n status: response.statusCode,\n headers,\n body: truncatedBody,\n ttfbMs: Math.round(ttfbMs),\n totalMs: Math.round(totalMs),\n contentType: headers['content-type'] ?? '',\n contentLength: truncatedBody.length,\n };\n } catch (err) {\n const totalMs = performance.now() - start;\n const message = err instanceof Error ? err.message : 'Unknown fetch error';\n // Surface undici's underlying cause (ENOTFOUND, ECONNREFUSED, timeout, TLS…)\n // so an opaque \"fetch failed\" becomes diagnosable in the logs.\n const code = errorCode(err);\n const detail = code ? `${message} (${code})` : message;\n\n logger.error(\n { url: targetUrl, err, code, totalMs: Math.round(totalMs) },\n `[fetcher] Fetch error: ${targetUrl} - ${detail}`,\n );\n\n return {\n url: targetUrl,\n finalUrl: targetUrl,\n status: 0,\n headers: {},\n body: '',\n ttfbMs: Math.round(ttfbMs || totalMs),\n totalMs: Math.round(totalMs),\n contentType: '',\n contentLength: 0,\n error: detail,\n };\n }\n }\n\n return { fetch };\n}\n","// ── URL Utilities ─────────────────────────────────────────────\n\nexport function normalizeUrl(input: string): string {\n let raw = input.trim();\n if (!/^https?:\\/\\//i.test(raw)) {\n raw = `https://${raw}`;\n }\n\n let parsed: URL;\n try {\n parsed = new URL(raw);\n } catch {\n throw new Error(`Invalid URL: ${input}`);\n }\n parsed.hostname = parsed.hostname.toLowerCase();\n\n let result = parsed.toString();\n if (result.endsWith('/') && parsed.pathname === '/') {\n result = result.slice(0, -1);\n }\n\n return result;\n}\n\nexport function joinUrl(base: string, path: string): string {\n const normalizedBase = base.endsWith('/') ? base.slice(0, -1) : base;\n const normalizedPath = path.startsWith('/') ? path : `/${path}`;\n return `${normalizedBase}${normalizedPath}`;\n}\n\nexport function extractDomain(url: string): string {\n try {\n const parsed = new URL(url);\n return parsed.hostname;\n } catch {\n throw new Error(`Invalid URL: ${url}`);\n }\n}\n\nconst PRIVATE_IPv4_PATTERNS = [\n /^10\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$/,\n /^172\\.(1[6-9]|2\\d|3[01])\\.\\d{1,3}\\.\\d{1,3}$/,\n /^192\\.168\\.\\d{1,3}\\.\\d{1,3}$/,\n /^127\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$/,\n /^169\\.254\\.\\d{1,3}\\.\\d{1,3}$/,\n /^0\\.0\\.0\\.0$/,\n];\n\nexport function isPrivateIp(ip: string): boolean {\n const trimmed = ip.trim();\n if (trimmed === '::1') return true;\n if (/^f[cd][0-9a-f]{2}:/i.test(trimmed)) return true;\n if (/^fe[89ab][0-9a-f]:/i.test(trimmed)) return true;\n\n const v4MappedMatch = trimmed.match(/^::ffff:(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})$/i);\n const candidate = v4MappedMatch ? v4MappedMatch[1] : trimmed;\n\n return PRIVATE_IPv4_PATTERNS.some((re) => re.test(candidate));\n}\n","import * as cheerio from 'cheerio';\nimport type { CheerioAPI } from 'cheerio';\nimport type { AnyNode, Element } from 'domhandler';\nimport type { PageType } from './types';\n\nexport function parseHtml(html: string): CheerioAPI {\n return cheerio.load(html);\n}\n\nexport function extractJsonLd($: CheerioAPI): object[] {\n const blocks: object[] = [];\n $('script[type=\"application/ld+json\"]').each((_, el) => {\n const raw = $(el).html();\n if (!raw) return;\n try {\n blocks.push(JSON.parse(raw));\n } catch {\n // Some platforms (e.g. Shopify themes) emit JSON-LD containing literal\n // control characters (raw newlines/tabs inside string values), which is\n // invalid JSON and makes strict JSON.parse throw — dropping otherwise\n // valid Product/Review blocks. Retry once with control chars stripped\n // before giving up.\n try {\n blocks.push(JSON.parse(raw.replace(/[\\x00-\\x1F]+/g, ' ')));\n } catch {\n // Genuinely malformed — left for the schema validation audit to flag.\n }\n }\n });\n return blocks;\n}\n\n/**\n * Flatten parsed JSON-LD into a flat list of schema.org nodes.\n *\n * Real-world JSON-LD nests the interesting types arbitrarily: a top-level\n * `[{...}]` array (common on Shopify), an `@graph` container, and properties\n * like `Product.aggregateRating`, `ProductGroup.hasVariant[].aggregateRating`,\n * `mainEntity`, `itemReviewed`, `offers`. The previous per-audit flatteners\n * only descended into `@graph`, so anything array-wrapped or nested was\n * invisible — producing false \"schema not found\" verdicts. This walks every\n * object and array value so type/property lookups see the whole graph.\n */\nexport function flattenJsonLd(blocks: object[]): object[] {\n const flat: object[] = [];\n const visit = (node: unknown, inheritedContext?: unknown): void => {\n if (Array.isArray(node)) {\n for (const n of node) visit(n, inheritedContext);\n return;\n }\n if (!node || typeof node !== 'object') return;\n const obj = node as Record<string, unknown>;\n const ctx = obj['@context'] ?? inheritedContext;\n if (!obj['@context'] && ctx) obj['@context'] = ctx;\n flat.push(obj);\n for (const value of Object.values(obj)) {\n if (value && typeof value === 'object') visit(value, ctx);\n }\n };\n for (const block of blocks) visit(block);\n return flat;\n}\n\n/**\n * Extract links from Markdown-ish text (llms.txt, READMEs).\n *\n * Real llms.txt files use many shapes the old line-anchored\n * `^-\\s*\\[label\\](url)` regex missed entirely: inline links inside prose,\n * bare-URL bullets (`- **Privacy**: https://…`), `*`/`+`/numbered bullets, and\n * indented/nested items. Returns `{ url, label, description }`, trimming the\n * trailing punctuation/markup (backticks, brackets, periods) that otherwise\n * corrupts the URL.\n */\nexport function extractMarkdownLinks(\n body: string,\n): Array<{ url: string; label: string; description: string }> {\n const out: Array<{ url: string; label: string; description: string }> = [];\n const seen = new Set<string>();\n const clean = (u: string) => u.replace(/[.,;:!?'\")\\]`>]+$/, '');\n const push = (url: string, label: string, description: string) => {\n const c = clean(url.trim());\n if (!/^https?:\\/\\//i.test(c) || seen.has(c)) return;\n seen.add(c);\n out.push({ url: c, label: label.trim(), description: description.trim() });\n };\n\n // 1. Inline Markdown links anywhere: [label](url) with optional \": desc\".\n const inline = /\\[([^\\]]+)\\]\\(([^)\\s]+)\\)(?::\\s*([^\\n]+))?/g;\n let m: RegExpExecArray | null;\n while ((m = inline.exec(body)) !== null) push(m[2]!, m[1]!, m[3] ?? '');\n\n // 2. Bare-URL list items: \"- **Label**: https://… — description\".\n const bullet = /^\\s*(?:[-*+]|\\d+\\.)\\s+(?:\\*\\*([^*]+)\\*\\*[:\\-—]?\\s*)?(https?:\\/\\/\\S+)\\s*(?:[-—:]\\s*(.+))?$/gm;\n while ((m = bullet.exec(body)) !== null) push(m[2]!, m[1] ?? '', m[3] ?? '');\n\n return out;\n}\n\n// ── Inline structured data (Microdata + RDFa) ──────────────────\n//\n// Many ecommerce platforms (e.g. Salesforce Commerce Cloud / Demandware)\n// express schema.org Product data as HTML Microdata (itemscope/itemtype/\n// itemprop) or RDFa (typeof/property) rather than JSON-LD. Search engines read\n// all three; the audits historically only saw JSON-LD. These extractors\n// normalize Microdata and RDFa into the same plain schema.org-shaped objects\n// (`@type` + properties, nested items recursed) so the existing Product audits\n// can consume them unchanged.\n\nconst TEXT_VALUE_MAX = 200;\n\n/** Nearest ancestor element carrying `attr` (e.g. 'itemscope'), or null. */\nfunction nearestScope(node: AnyNode, attr: string): Element | null {\n let p: AnyNode | null = node.parent as AnyNode | null;\n while (p) {\n if (p.type === 'tag' && attr in (p as Element).attribs) return p as Element;\n p = p.parent as AnyNode | null;\n }\n return null;\n}\n\n/** Last path/fragment segment of each space-separated term in a type value. */\nfunction termsFromType(raw: string): string | string[] {\n const terms = raw\n .split(/\\s+/)\n .filter(Boolean)\n .map((t) => t.replace(/[/#:]+$/, '').split(/[/#:]/).pop() || t);\n return terms.length === 1 ? terms[0]! : terms;\n}\n\n/** First term of a property name, stripped of any vocab prefix/URL. */\nfunction firstTerm(raw: string | undefined): string {\n if (!raw) return '';\n const t = raw.split(/\\s+/).filter(Boolean)[0] ?? '';\n return t.split(/[/#:]/).pop() || t;\n}\n\n/** Resolve the value of a property element per the Microdata/RDFa value rules. */\nfunction propValue($: CheerioAPI, el: Element): string {\n /* v8 ignore next -- domhandler elements always have `attribs`; the `?? {}` guard is unreachable. */\n const a = el.attribs ?? {};\n if (a.content) return a.content;\n /* v8 ignore next -- tag elements always have a `name`; the `?? ''` guard is unreachable. */\n switch ((el.name ?? '').toLowerCase()) {\n case 'meta':\n return a.content ?? '';\n case 'a':\n case 'link':\n case 'area':\n return a.href ?? '';\n case 'img':\n case 'audio':\n case 'video':\n case 'source':\n case 'iframe':\n case 'embed':\n case 'track':\n return a.src ?? '';\n case 'object':\n return a.data ?? '';\n case 'data':\n case 'meter':\n return a.value ?? '';\n case 'time':\n return a.datetime ?? $(el).text().replace(/\\s+/g, ' ').trim().slice(0, TEXT_VALUE_MAX);\n default:\n return $(el).text().replace(/\\s+/g, ' ').trim().slice(0, TEXT_VALUE_MAX);\n }\n}\n\n/** Assign a property, collapsing repeats into an array. Splits multi-name props. */\nfunction addProp(obj: Record<string, unknown>, rawName: string, value: unknown): void {\n for (const name of rawName.split(/\\s+/).filter(Boolean)) {\n const existing = obj[name];\n if (existing === undefined) {\n obj[name] = value;\n } else if (Array.isArray(existing)) {\n existing.push(value);\n } else {\n obj[name] = [existing, value];\n }\n }\n}\n\nfunction parseMicrodataItem($: CheerioAPI, el: Element): Record<string, unknown> {\n const obj: Record<string, unknown> = {};\n const itemtype = el.attribs?.itemtype;\n if (itemtype) {\n obj['@context'] = 'https://schema.org';\n obj['@type'] = termsFromType(itemtype);\n }\n $(el)\n .find('[itemprop]')\n .each((_, raw) => {\n const propEl = raw as Element;\n // Only properties whose nearest itemscope is THIS element belong here;\n // properties of nested items are captured when that item is recursed.\n if (nearestScope(propEl, 'itemscope') !== el) return;\n const name = propEl.attribs?.itemprop;\n if (!name) return;\n /* v8 ignore next 2 -- domhandler elements always have `attribs`; the `?? {}` guard is unreachable. */\n const value =\n 'itemscope' in (propEl.attribs ?? {}) ? parseMicrodataItem($, propEl) : propValue($, propEl);\n addProp(obj, name, value);\n });\n return obj;\n}\n\nexport function extractMicrodata($: CheerioAPI): object[] {\n const items: object[] = [];\n $('[itemscope]').each((_, raw) => {\n const el = raw as Element;\n if (nearestScope(el, 'itemscope')) return; // nested — handled by its parent item\n items.push(parseMicrodataItem($, el));\n });\n return items;\n}\n\nfunction parseRdfaItem($: CheerioAPI, el: Element): Record<string, unknown> {\n const obj: Record<string, unknown> = { '@context': 'https://schema.org' };\n const typeName = el.attribs?.typeof;\n if (typeName) obj['@type'] = termsFromType(typeName);\n $(el)\n .find('[property]')\n .each((_, raw) => {\n const propEl = raw as Element;\n if (nearestScope(propEl, 'typeof') !== el) return;\n const name = firstTerm(propEl.attribs?.property);\n if (!name) return;\n /* v8 ignore next 2 -- domhandler elements always have `attribs`; the `?? {}` guard is unreachable. */\n const value =\n 'typeof' in (propEl.attribs ?? {}) ? parseRdfaItem($, propEl) : propValue($, propEl);\n addProp(obj, name, value);\n });\n return obj;\n}\n\nexport function extractRdfa($: CheerioAPI): object[] {\n const items: object[] = [];\n $('[typeof]').each((_, raw) => {\n const el = raw as Element;\n if (nearestScope(el, 'typeof')) return; // nested — handled by its parent item\n items.push(parseRdfaItem($, el));\n });\n return items;\n}\n\nexport function extractMetaTags($: CheerioAPI): Record<string, string> {\n const meta: Record<string, string> = {};\n $('meta').each((_, el) => {\n const name = $(el).attr('name') || $(el).attr('property') || $(el).attr('http-equiv');\n const content = $(el).attr('content');\n if (name && content) {\n meta[name.toLowerCase()] = content;\n }\n });\n return meta;\n}\n\nexport interface HeadLink {\n rel: string;\n type: string;\n href: string;\n title: string;\n}\n\nexport function extractHeadLinks($: CheerioAPI): HeadLink[] {\n const links: HeadLink[] = [];\n // Search both <head> and the full document for <link> tags.\n // Frameworks like Next.js App Router stream metadata outside the\n // initial <head> shell, so limiting to `head link` misses them.\n $('link').each((_, el) => {\n const rel = $(el).attr('rel') ?? '';\n // Skip stylesheet links outside <head> to avoid noise\n if (!rel || rel === 'stylesheet' || rel === 'preload') return;\n links.push({\n rel,\n type: $(el).attr('type') ?? '',\n href: $(el).attr('href') ?? '',\n title: $(el).attr('title') ?? '',\n });\n });\n return links;\n}\n\nexport function extractHeadings($: CheerioAPI): Array<{ level: number; text: string }> {\n const headings: Array<{ level: number; text: string }> = [];\n $('h1, h2, h3, h4, h5, h6').each((_, el) => {\n /* v8 ignore next -- matched heading elements always expose `tagName`; the `?? ''` guard is unreachable. */\n const tag = $(el).prop('tagName')?.toLowerCase() ?? '';\n const level = parseInt(tag.replace('h', ''), 10);\n headings.push({ level, text: $(el).text().trim() });\n });\n return headings;\n}\n\nexport function getMainContentText($: CheerioAPI): string {\n const root = $('main').first().length ? $('main').first() : $('body');\n // cheerio's .text() concatenates the bodies of <script>/<style>/<noscript>\n // tags too. On modern themes those hold megabytes of inline JSON/JS/CSS that\n // pollute every downstream content regex (dates, numbers, keywords) with\n // garbage matches. Clone the subtree (so we never mutate the shared DOM other\n // audits read) and drop non-content nodes before extracting text.\n const clone = root.clone();\n clone.find('script, style, noscript, template').remove();\n return clone.text().replace(/\\s+/g, ' ').trim();\n}\n\nexport function getWordCount($: CheerioAPI): number {\n const text = getMainContentText($);\n return text.split(/\\s+/).filter(Boolean).length;\n}\n\nexport function extractImages($: CheerioAPI): Array<{\n src: string;\n alt: string;\n hasAlt: boolean;\n width?: string;\n height?: string;\n loading?: string;\n role?: string;\n}> {\n const images: Array<{\n src: string;\n alt: string;\n hasAlt: boolean;\n width?: string;\n height?: string;\n loading?: string;\n role?: string;\n }> = [];\n $('img').each((_, el) => {\n const alt = $(el).attr('alt');\n images.push({\n src: $(el).attr('src') ?? '',\n alt: alt ?? '',\n // Whether the alt attribute is present at all. Distinguishes an\n // intentionally empty `alt=\"\"` (decorative) from a missing attribute.\n hasAlt: alt !== undefined,\n width: $(el).attr('width') ?? undefined,\n height: $(el).attr('height') ?? undefined,\n loading: $(el).attr('loading') ?? undefined,\n role: $(el).attr('role') ?? undefined,\n });\n });\n return images;\n}\n\nexport function extractForms($: CheerioAPI): Array<{\n action: string;\n method: string;\n inputs: Array<{\n name: string;\n type: string;\n label?: string;\n required: boolean;\n }>;\n}> {\n const forms: Array<{\n action: string;\n method: string;\n inputs: Array<{\n name: string;\n type: string;\n label?: string;\n required: boolean;\n }>;\n }> = [];\n $('form').each((_, formEl) => {\n const inputs: Array<{\n name: string;\n type: string;\n label?: string;\n required: boolean;\n }> = [];\n $(formEl)\n .find('input, select, textarea')\n .each((_j, inputEl) => {\n const id = $(inputEl).attr('id');\n let label: string | undefined;\n if (id) {\n const labelEl = $(`label[for=\"${id}\"]`);\n if (labelEl.length) {\n label = labelEl.text().trim();\n }\n }\n /* v8 ignore next -- matched form controls always expose `tagName`; the `?? 'input'` guard is unreachable. */\n const tagName = $(inputEl).prop('tagName')?.toLowerCase() ?? 'input';\n inputs.push({\n name: $(inputEl).attr('name') ?? '',\n type: tagName === 'input' ? ($(inputEl).attr('type') ?? 'text') : tagName,\n label,\n required: $(inputEl).attr('required') !== undefined,\n });\n });\n forms.push({\n action: $(formEl).attr('action') ?? '',\n method: ($(formEl).attr('method') ?? 'GET').toUpperCase(),\n inputs,\n });\n });\n return forms;\n}\n\nexport function extractInternalLinks($: CheerioAPI, domain: string): string[] {\n const seen = new Set<string>();\n $('a[href]').each((_, el) => {\n const href = $(el).attr('href');\n if (!href) return;\n try {\n const url = new URL(href, `https://${domain}`);\n if (url.hostname === domain || url.hostname.endsWith(`.${domain}`)) {\n seen.add(url.href);\n }\n } catch {\n // Ignore invalid URLs\n }\n });\n return [...seen];\n}\n\nexport function extractNavLinks($: CheerioAPI): string[] {\n const links: string[] = [];\n $('nav a[href]').each((_, el) => {\n const href = $(el).attr('href');\n if (href) {\n links.push(href);\n }\n });\n return links;\n}\n\nexport function extractScripts($: CheerioAPI): Array<{\n src?: string;\n async: boolean;\n defer: boolean;\n type?: string;\n isModule: boolean;\n noModule: boolean;\n inline: boolean;\n}> {\n const scripts: Array<{\n src?: string;\n async: boolean;\n defer: boolean;\n type?: string;\n isModule: boolean;\n noModule: boolean;\n inline: boolean;\n }> = [];\n $('script').each((_, el) => {\n const src = $(el).attr('src') ?? undefined;\n const type = $(el).attr('type') ?? undefined;\n scripts.push({\n src,\n async: $(el).attr('async') !== undefined,\n defer: $(el).attr('defer') !== undefined,\n type,\n isModule: type === 'module',\n noModule: $(el).attr('nomodule') !== undefined,\n inline: src === undefined,\n });\n });\n return scripts;\n}\n\nexport function extractStylesheetUrls($: CheerioAPI): string[] {\n const urls: string[] = [];\n $('link[rel=\"stylesheet\"]').each((_, el) => {\n const href = $(el).attr('href');\n if (href) {\n urls.push(href);\n }\n });\n return urls;\n}\n\n// ── Page Type Detection ───────────────────────────────────────\n\n/**\n * Detect whether a page is a Homepage, Category Page, Product Details Page,\n * or Content Page based on URL patterns, JSON-LD schemas, meta tags, and\n * HTML signals typical of ecommerce websites.\n */\nexport function detectPageType(\n url: string,\n $: CheerioAPI,\n jsonLd: object[],\n meta: Record<string, string>,\n isFirstPage: boolean,\n): PageType {\n const pathname = new URL(url).pathname.toLowerCase();\n\n // ── 1. Homepage ─────────────────────────────────────────────\n if (isFirstPage && (pathname === '/' || pathname === '')) {\n return 'homepage';\n }\n\n // ── 2. Product Details Page (check before category) ─────────\n if (isProductPage(pathname, $, jsonLd, meta)) {\n return 'product';\n }\n\n // ── 3. Category / Listing Page ──────────────────────────────\n if (isCategoryPage(pathname, $, jsonLd)) {\n return 'category';\n }\n\n // ── 4. Fallback: Content Page ───────────────────────────────\n return 'content';\n}\n\nfunction isProductPage(\n pathname: string,\n $: CheerioAPI,\n jsonLd: object[],\n meta: Record<string, string>,\n): boolean {\n // JSON-LD Product schema\n if (hasJsonLdType(jsonLd, ['Product', 'IndividualProduct', 'ProductModel'])) {\n return true;\n }\n\n // og:type = product or product.item\n const ogType = (meta['og:type'] ?? '').toLowerCase();\n if (ogType === 'product' || ogType === 'product.item' || ogType === 'og:product') {\n return true;\n }\n\n // URL patterns common in ecommerce product pages\n if (\n /\\/(product|products|p|item|dp|gp\\/product|shop\\/[^/]+\\/[^/]+)\\/[^/]+/i.test(pathname) ||\n /\\/(product|item|sku)-[a-z0-9-]+/i.test(pathname)\n ) {\n return true;\n }\n\n // HTML signals: add-to-cart button/form, price elements\n const hasAddToCart =\n $(\n '[class*=\"add-to-cart\"], [id*=\"add-to-cart\"], button:contains(\"Add to Cart\"), button:contains(\"Add to Bag\"), [data-action=\"add-to-cart\"]',\n ).length > 0;\n const hasPrice =\n $(\n '[class*=\"product-price\"], [class*=\"product__price\"], [itemprop=\"price\"], [data-price], .price',\n ).length > 0;\n\n if (hasAddToCart && hasPrice) {\n return true;\n }\n\n return false;\n}\n\nfunction isCategoryPage(pathname: string, $: CheerioAPI, jsonLd: object[]): boolean {\n // JSON-LD CollectionPage or ItemList schema\n if (hasJsonLdType(jsonLd, ['CollectionPage', 'ItemList', 'OfferCatalog', 'ProductCollection'])) {\n return true;\n }\n\n // URL patterns common in ecommerce category/listing pages\n if (\n /^\\/(category|categories|c|collections?|shop|catalog|department|browse)(\\/|$)/i.test(\n pathname,\n ) ||\n /^\\/(men|women|kids|sale|new-arrivals|best-sellers)(\\/|$)/i.test(pathname)\n ) {\n return true;\n }\n\n // HTML signals: product grid/list with multiple product cards\n const productCards = $(\n '[class*=\"product-card\"], [class*=\"product-item\"], [class*=\"product-tile\"], [data-product-id], [class*=\"product-grid\"] > *, [class*=\"product-list\"] > *',\n );\n if (productCards.length >= 3) {\n return true;\n }\n\n // Pagination + multiple items suggests a listing\n const hasPagination =\n $('[class*=\"pagination\"], nav[aria-label*=\"pagination\"], .pager, [class*=\"load-more\"]').length >\n 0;\n const hasFilterOrSort =\n $('[class*=\"filter\"], [class*=\"facet\"], [class*=\"sort-by\"], [data-filter]').length > 0;\n\n if (hasPagination && hasFilterOrSort) {\n return true;\n }\n\n return false;\n}\n\nfunction hasJsonLdType(jsonLd: object[], types: string[]): boolean {\n for (const block of jsonLd) {\n const b = block as Record<string, unknown>;\n\n // Check top-level @type\n const blockType = b['@type'];\n if (typeof blockType === 'string' && types.includes(blockType)) return true;\n if (Array.isArray(blockType) && blockType.some((t) => types.includes(t))) return true;\n\n // Check inside @graph\n if (Array.isArray(b['@graph'])) {\n for (const item of b['@graph']) {\n if (item && typeof item === 'object') {\n const itemType = (item as Record<string, unknown>)['@type'];\n if (typeof itemType === 'string' && types.includes(itemType)) return true;\n if (Array.isArray(itemType) && itemType.some((t: unknown) => types.includes(t as string)))\n return true;\n }\n }\n }\n }\n return false;\n}\n","import { z } from 'zod';\n\nexport const CheckStatusSchema = z.enum(['pass', 'warn', 'fail', 'na']);\nexport const CheckPrioritySchema = z.enum(['critical', 'high', 'medium', 'low']);\n\nexport const AuditResultSchema = z.object({\n status: CheckStatusSchema,\n score: z.number().min(0).max(1),\n displayValue: z.string().max(1000).optional(),\n explanation: z.string().max(5000).optional(),\n expected: z.string().max(10000).optional(),\n found: z.string().max(10000).optional(),\n message: z.string().max(5000).optional(),\n details: z\n .object({\n expected: z.string().max(10000).optional(),\n found: z.string().max(10000).optional(),\n code: z.string().max(10000).optional(),\n })\n .optional(),\n pageUrl: z.string().max(2048).url().optional().or(z.string().max(2048).startsWith('/')).or(z.string().length(0)),\n priority: CheckPrioritySchema.optional(),\n code: z.string().max(10000).optional(),\n});\n\nexport const FixEffortSchema = z.enum(['trivial', 'easy', 'moderate', 'complex']);\n\nexport const AuditGuidanceSchema = z.object({\n impact: z.string().max(5000),\n fix: z.string().max(5000),\n code: z.string().max(10000).optional(),\n effort: FixEffortSchema,\n docsUrl: z.string().max(2048).url().optional().or(z.string().length(0)),\n tags: z.array(z.string().max(50)).max(20).optional(),\n});\n\nexport const ScoreDisplayModeSchema = z.enum(['binary', 'ternary', 'informative']);\n\nexport const AuditMetaSchema = z.object({\n id: z.string(),\n category: z.string(),\n title: z.string(),\n failureTitle: z.string(),\n description: z.string(),\n scoreDisplayMode: ScoreDisplayModeSchema,\n weight: z.number().positive(),\n applicablePageTypes: z.array(z.string()).optional(),\n defaultPriority: CheckPrioritySchema,\n guidance: AuditGuidanceSchema.optional(),\n});\n\nexport const CheckResultSchema = z.object({\n id: z.string().max(20),\n category: z.string().max(100),\n title: z.string().max(500),\n description: z.string().max(5000),\n status: CheckStatusSchema,\n score: z.number().min(0).max(1),\n scoreDisplayMode: ScoreDisplayModeSchema,\n displayValue: z.string().max(1000).optional(),\n explanation: z.string().max(5000).optional(),\n pageUrl: z.string().max(2048).url().optional().or(z.string().max(2048).startsWith('/')).or(z.string().length(0)),\n priority: CheckPrioritySchema,\n impact: z.string().max(5000),\n fix: z.string().max(5000),\n details: z\n .object({\n expected: z.string().max(10000).optional(),\n found: z.string().max(10000).optional(),\n code: z.string().max(10000).optional(),\n docsUrl: z.string().max(2048).url().optional().or(z.string().length(0)),\n })\n .optional(),\n tags: z.array(z.string().max(50)).max(20).optional(),\n});\n","import type { AuditMeta, AuditResult, CheckResult, CheckPriority } from './types';\nimport { AuditResultSchema } from './schemas';\nimport type { CheckContext } from './check-context';\n\n/**\n * Base class for all audits. Follows the Lighthouse pattern:\n * each audit is a class with a static `meta` descriptor and\n * an `audit()` method that receives the scan context.\n */\nexport abstract class Audit {\n static meta: AuditMeta;\n private static readonly PRIORITY_MAP: Record<string, CheckPriority> = {\n critical: 'critical',\n high: 'high',\n medium: 'medium',\n low: 'low',\n };\n\n /** Validate an audit result against the schema. */\n protected validate(result: AuditResult): AuditResult {\n if (result.found && result.found.length > 5000) {\n result.found = result.found.slice(0, 4990) + '... (truncated)';\n }\n if (result.expected && result.expected.length > 5000) {\n result.expected = result.expected.slice(0, 4990) + '... (truncated)';\n }\n return AuditResultSchema.parse(result);\n }\n\n /** Run the audit and return a result. */\n abstract audit(ctx: CheckContext): AuditResult | Promise<AuditResult>;\n\n /** Create a passing result. */\n protected pass(message: string, expected: string, found: string, pageUrl?: string): AuditResult {\n return { status: 'pass', score: 1.0, message, expected, found, pageUrl };\n }\n\n /**\n * Create a not-applicable result. Use when the audit's precondition is\n * absent (e.g. a quality check on a feature the site doesn't implement at\n * all). Excluded from score aggregation so it neither inflates nor deflates\n * the category score — unlike a vacuous `pass()`, which rewards absence.\n */\n protected notApplicable(message: string, expected: string, found: string, pageUrl?: string): AuditResult {\n return { status: 'na', score: 0, message, expected, found, pageUrl };\n }\n\n /** Create a warning result. */\n protected warn(\n message: string,\n expected: string,\n found: string,\n recommendationOrPriority?:\n | { priority: CheckPriority; [key: string]: unknown }\n | string,\n pageUrl?: string,\n ): AuditResult {\n const priority =\n typeof recommendationOrPriority === 'string'\n ? recommendationOrPriority\n : (recommendationOrPriority as { priority: CheckPriority })?.priority;\n\n return {\n status: 'warn',\n score: 0.5,\n message,\n expected,\n found,\n priority:\n (typeof priority === 'string' ? Audit.PRIORITY_MAP[priority] : undefined) ??\n (priority as CheckPriority),\n pageUrl,\n };\n }\n\n /** Create a failing result. */\n protected fail(\n message: string,\n expected: string,\n found: string,\n recommendationOrPriority?:\n | { priority: CheckPriority; [key: string]: unknown }\n | string,\n pageUrl?: string,\n ): AuditResult {\n const priority =\n typeof recommendationOrPriority === 'string'\n ? recommendationOrPriority\n : (recommendationOrPriority as { priority: CheckPriority })?.priority;\n\n return {\n status: 'fail',\n score: 0.0,\n message,\n expected,\n found,\n priority:\n (typeof priority === 'string' ? Audit.PRIORITY_MAP[priority] : undefined) ??\n (priority as CheckPriority),\n pageUrl,\n };\n }\n\n /** Merge static meta with the runtime result to produce a CheckResult. */\n toCheckResult(rawResult: AuditResult): CheckResult {\n const result = this.validate(rawResult);\n const meta = (this.constructor as typeof Audit).meta;\n\n // Backward compatibility mapping\n const displayValue = result.displayValue ?? result.found ?? result.message;\n const explanation = result.explanation ?? result.message;\n const expected = result.details?.expected ?? result.expected;\n const found = result.details?.found ?? result.found;\n\n return {\n id: meta.id,\n category: meta.category,\n title: result.status === 'pass' ? meta.title : meta.failureTitle,\n description: meta.description,\n status: result.status,\n score: result.score,\n scoreDisplayMode: meta.scoreDisplayMode,\n displayValue,\n explanation,\n pageUrl: result.pageUrl,\n\n // UCP guidance extensions\n priority: result.priority ?? meta.defaultPriority,\n impact: meta.guidance?.impact ?? meta.description,\n fix: meta.guidance?.fix ?? 'No fix instructions available.',\n\n // Structured details\n details: {\n ...result.details,\n expected,\n found,\n code: result.details?.code ?? meta.guidance?.code,\n docsUrl: meta.guidance?.docsUrl,\n effort: meta.guidance?.effort,\n },\n tags: meta.guidance?.tags,\n };\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\nimport type { FetchResult } from '../../fetcher';\n\nfunction isOk(result: FetchResult): boolean {\n return result.status === 200;\n}\n\nexport class LlmsTxtExistsAudit extends Audit {\n static override meta: AuditMeta = {\n id: '1.1',\n category: 'content-discoverability',\n title: 'llms.txt exists',\n failureTitle: 'llms.txt exists',\n description:\n 'llms.txt is the primary way AI agents discover your site content. Without it, LLMs must crawl your entire site to understand what you offer. Create this file at your site root.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'critical',\n guidance: {\n impact:\n 'llms.txt is the primary entry point for AI agents discovering your site. Without it, LLMs like ChatGPT, Perplexity, and Claude must crawl your entire site blindly, often missing key pages and providing incomplete or inaccurate answers about your business.',\n fix: 'Create a /llms.txt file at your site root in markdown format. Include an H1 heading with your site name, a blockquote summary, and organized sections with links to your key pages.',\n code: '# Your Site Name\\n\\n> Brief description of your site for AI agents.\\n\\n## Pages\\n- [Home](/): Main landing page\\n- [About](/about/): Company information\\n\\n## Resources\\n- [Sitemap](/sitemap.xml): Full URL list\\n- [RSS](/rss.xml): Content feed',\n effort: 'easy',\n docsUrl: 'https://llmstxt.org/',\n tags: ['llms-txt', 'discoverability'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const result = ctx.rootFiles['/llms.txt'];\n\n if (!result || !isOk(result)) {\n return this.fail(\n 'llms.txt not found at site root.',\n 'GET /llms.txt returns 200 with markdown starting with #',\n result ? `HTTP ${result.status}` : 'No response',\n 'critical',\n );\n }\n\n if (!result.body.trimStart().startsWith('#')) {\n return this.warn(\n 'llms.txt missing markdown heading.',\n 'Body starts with # (H1 heading)',\n `Body starts with \"${result.body.trimStart().slice(0, 40)}...\"`,\n 'high',\n );\n }\n\n return this.pass(\n 'llms.txt exists and is valid.',\n 'HTTP 200 with # heading',\n 'HTTP 200 with # heading',\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\nimport type { FetchResult } from '../../fetcher';\n\nfunction isOk(result: FetchResult): boolean {\n return result.status === 200;\n}\n\nexport class LlmsTxtBlockquoteAudit extends Audit {\n static override meta: AuditMeta = {\n id: '1.2',\n category: 'content-discoverability',\n title: 'llms.txt has blockquote summary',\n failureTitle: 'llms.txt has blockquote summary',\n description:\n 'The blockquote summary gives AI agents a one-sentence overview of your site without reading further.',\n scoreDisplayMode: 'binary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'Without a blockquote summary, AI agents have no quick way to understand what your site offers. They must parse the entire llms.txt file before deciding if your content is relevant, leading to slower and less accurate AI responses about your business.',\n fix: 'Add a blockquote line (starting with >) immediately after the H1 heading in your llms.txt file. Write a concise 1-2 sentence summary of what your site provides.',\n code: '# Your Site Name\\n\\n> Your site provides X for Y. It covers topics including A, B, and C.',\n effort: 'trivial',\n docsUrl: 'https://llmstxt.org/',\n tags: ['llms-txt', 'discoverability'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const result = ctx.rootFiles['/llms.txt'];\n\n if (!result || !isOk(result)) {\n return this.fail(\n 'llms.txt not found; cannot check for blockquote summary.',\n '> blockquote line after H1',\n 'File not found',\n {\n priority: 'critical',\n description:\n 'First, create your llms.txt file (see check 1.1). The blockquote summary gives AI agents a one-sentence overview of your site without reading further.',\n code: `# Your Site Name\\n\\n> Brief description of your site for AI agents.\\n\\n## Pages\\n- [Home](/): Main landing page\\n- [About](/about/): Company information`,\n },\n );\n }\n\n const lines = result.body.split('\\n');\n const h1Index = lines.findIndex((l) => l.trimStart().startsWith('# '));\n if (h1Index === -1) {\n return this.fail('No H1 heading found in llms.txt.', '> blockquote after H1', 'No H1 found', {\n priority: 'high',\n description:\n 'llms.txt needs an H1 heading before the blockquote summary. AI agents use the heading to identify your site and the blockquote as a concise summary.',\n code: `# Your Site Name\\n\\n> Brief description of what your site offers to AI agents.`,\n });\n }\n\n // Look for a blockquote line after the H1\n const afterH1 = lines.slice(h1Index + 1);\n const hasBlockquote = afterH1.some((l) => l.trimStart().startsWith('> '));\n\n if (!hasBlockquote) {\n return this.fail(\n 'llms.txt has no blockquote summary after the H1 heading.',\n '> blockquote summary line after H1',\n 'No > line found after H1',\n {\n priority: 'medium',\n description:\n 'The blockquote summary gives AI agents a concise overview of your site in 1-2 sentences. It appears right after the H1 heading and helps agents decide whether your site is relevant to a user query.',\n code: `> Your site provides X for Y. It covers topics including A, B, and C.`,\n },\n );\n }\n\n return this.pass(\n 'llms.txt contains a blockquote summary after the H1 heading.',\n '> blockquote after H1',\n 'Blockquote found',\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\nimport type { FetchResult } from '../../fetcher';\n\nfunction isOk(result: FetchResult): boolean {\n return result.status === 200;\n}\n\nexport class LlmsTxtSectionsAudit extends Audit {\n static override meta: AuditMeta = {\n id: '1.3',\n category: 'content-discoverability',\n title: 'llms.txt has H2 sections',\n failureTitle: 'llms.txt has H2 sections',\n description:\n 'H2 sections help AI agents navigate your llms.txt by topic. Without them, agents must scan the entire file linearly.',\n scoreDisplayMode: 'binary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'Without H2 sections, AI agents must scan your entire llms.txt linearly to find relevant content. Sections let agents jump directly to the topic they need, producing faster and more accurate responses.',\n fix: 'Organize your llms.txt links under H2 headings (## Section Name) that group related pages. Use intuitive section names like ## Documentation, ## API, ## Blog, ## Company.',\n code: '## Documentation\\n- [Getting Started](/docs/start): Quick start guide\\n- [API Reference](/docs/api): Full API documentation\\n\\n## Company\\n- [About](/about): Company information\\n- [Blog](/blog): Latest updates',\n effort: 'trivial',\n docsUrl: 'https://llmstxt.org/',\n tags: ['llms-txt', 'discoverability'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const result = ctx.rootFiles['/llms.txt'];\n\n if (!result || !isOk(result)) {\n return this.fail(\n 'llms.txt not found; cannot check for H2 sections.',\n 'At least one ## heading',\n 'File not found',\n {\n priority: 'critical',\n description:\n 'First, create your llms.txt file (see check 1.1). H2 sections organize your content into logical groups so AI agents can quickly navigate to relevant information.',\n code: `# Your Site Name\\n\\n> Brief description of your site for AI agents.\\n\\n## Pages\\n- [Home](/): Main landing page\\n- [About](/about/): Company information`,\n },\n );\n }\n\n const h2Lines = result.body.split('\\n').filter((l) => /^##\\s/.test(l.trimStart()));\n\n if (h2Lines.length === 0) {\n return this.fail(\n 'llms.txt has no H2 sections to organize content.',\n 'At least one ## heading',\n 'No ## headings found',\n {\n priority: 'medium',\n description:\n 'H2 sections help AI agents navigate your llms.txt by topic. Without them, agents must scan the entire file linearly. Use sections like ## Documentation, ## API, ## Blog to group related links.',\n code: `## Documentation\\n- [Getting Started](/docs/start): Quick start guide\\n- [API Reference](/docs/api): Full API documentation\\n\\n## Company\\n- [About](/about): Company information\\n- [Blog](/blog): Latest updates`,\n },\n );\n }\n\n return this.pass(\n `llms.txt has ${h2Lines.length} H2 section(s).`,\n 'At least one ## heading',\n `${h2Lines.length} ## heading(s) found`,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\nimport type { FetchResult } from '../../fetcher';\nimport { extractMarkdownLinks } from '../../parser';\n\nfunction isOk(result: FetchResult): boolean {\n return result.status === 200;\n}\n\nexport class LlmsTxtLinkDescriptionsAudit extends Audit {\n static override meta: AuditMeta = {\n id: '1.4',\n category: 'content-discoverability',\n title: 'llms.txt links include descriptions',\n failureTitle: 'llms.txt links include descriptions',\n description:\n 'Link descriptions help AI agents understand what each page covers without visiting it, reducing unnecessary crawling.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'Links without descriptions force AI agents to visit every page to understand its content, wasting crawl budget and slowing down response generation. Described links let agents filter relevant pages instantly.',\n fix: 'Add a colon and brief description after each link URL in your llms.txt file. Describe what the page covers in a few words so agents can decide which pages to visit.',\n code: '- [Getting Started](/docs/start): Step-by-step guide for new users\\n- [API Reference](/docs/api): Complete endpoint documentation\\n- [Pricing](/pricing): Plans and pricing information',\n effort: 'trivial',\n docsUrl: 'https://llmstxt.org/',\n tags: ['llms-txt', 'discoverability'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const result = ctx.rootFiles['/llms.txt'];\n\n if (!result || !isOk(result)) {\n return this.fail(\n 'llms.txt not found; cannot check link descriptions.',\n 'Links follow - [Name](url): description',\n 'File not found',\n {\n priority: 'critical',\n description:\n 'First, create your llms.txt file (see check 1.1). Link descriptions help AI agents understand what each page covers without visiting it, reducing unnecessary crawling.',\n code: `# Your Site Name\\n\\n> Brief description of your site for AI agents.\\n\\n## Pages\\n- [Home](/): Main landing page\\n- [About](/about/): Company information`,\n },\n );\n }\n\n const links = extractMarkdownLinks(result.body);\n\n if (links.length === 0) {\n return this.warn(\n 'llms.txt contains no markdown links.',\n 'Links follow - [Name](url): description pattern',\n 'No links found',\n {\n priority: 'medium',\n description:\n 'Without links, AI agents cannot discover your pages from llms.txt. Add links to your most important pages using the markdown list format with descriptions so agents know what each page covers.',\n code: `- [Getting Started](/docs/start): Step-by-step guide for new users\\n- [API Reference](/docs/api): Complete endpoint documentation\\n- [Pricing](/pricing): Plans and pricing information`,\n },\n );\n }\n\n const withDescription = links.filter((l) => l.description.length > 0);\n const ratio = withDescription.length / links.length;\n\n if (ratio < 0.5) {\n return this.fail(\n `Only ${withDescription.length}/${links.length} links have descriptions.`,\n 'All links follow - [Name](url): description',\n `${withDescription.length}/${links.length} have descriptions`,\n {\n priority: 'medium',\n description:\n 'Link descriptions help AI agents decide which pages to visit without crawling them all. Add a colon and brief description after each link URL explaining what the page covers.',\n code: `- [Page Name](/path): Brief description of the page content and purpose`,\n },\n );\n }\n\n if (ratio < 1.0) {\n return this.warn(\n `${withDescription.length}/${links.length} links have descriptions.`,\n 'All links follow - [Name](url): description',\n `${withDescription.length}/${links.length} have descriptions`,\n {\n priority: 'low',\n description:\n 'Some links are missing descriptions. Adding descriptions to all links helps AI agents efficiently filter relevant pages without visiting each one.',\n code: `- [Page Name](/path): Brief description of the page content and purpose`,\n },\n );\n }\n\n return this.pass(\n `All ${links.length} links include descriptions.`,\n 'All links have descriptions',\n `${links.length}/${links.length} have descriptions`,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\nimport { type FetchResult, isSafeUrl } from '../../fetcher';\nimport { extractMarkdownLinks } from '../../parser';\n\nfunction isOk(result: FetchResult): boolean {\n return result.status === 200;\n}\n\nexport class LlmsTxtLinksValidAudit extends Audit {\n static override meta: AuditMeta = {\n id: '1.5',\n category: 'content-discoverability',\n title: 'llms.txt links are valid',\n failureTitle: 'llms.txt links are valid',\n description:\n 'Valid links in llms.txt ensure AI agents can navigate to your content without encountering dead ends.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'high',\n guidance: {\n impact:\n 'Broken links in llms.txt send AI agents to dead ends, wasting their context window and degrading the quality of answers about your site. Users asking AI about your products or services will get error messages instead of useful information.',\n fix: 'Verify all links in your llms.txt resolve to HTTP 200. Remove links to deleted pages and update any URLs that have changed. Run this check after every site deployment.',\n code: '- [Page Name](/correct-path): Description of the page content',\n effort: 'easy',\n docsUrl: 'https://llmstxt.org/',\n tags: ['llms-txt', 'broken-links', 'discoverability'],\n },\n };\n\n async audit(ctx: CheckContext): Promise<AuditResult> {\n const result = ctx.rootFiles['/llms.txt'];\n\n if (!result || !isOk(result)) {\n return this.fail(\n 'llms.txt not found; cannot validate links.',\n 'All links return HTTP 200',\n 'File not found',\n {\n priority: 'critical',\n description:\n 'First, create your llms.txt file (see check 1.1). Valid links in llms.txt ensure AI agents can navigate to your content without encountering dead ends.',\n code: `# Your Site Name\\n\\n> Brief description of your site for AI agents.\\n\\n## Pages\\n- [Home](/): Main landing page\\n- [About](/about/): Company information`,\n },\n );\n }\n\n const links = extractMarkdownLinks(result.body);\n\n if (links.length === 0) {\n return this.warn(\n 'No links found in llms.txt to validate.',\n 'All links return HTTP 200',\n 'No links found',\n {\n priority: 'medium',\n description:\n 'llms.txt should contain links to your key pages. Without links, the file does not help AI agents discover your content.',\n code: `- [Home](/): Main landing page\\n- [About](/about/): Company information`,\n },\n );\n }\n\n // Resolve relative URLs and filter out unsafe ones (SSRF protection)\n const resolved: string[] = [];\n for (const l of links) {\n try {\n const abs = new URL(l.url, ctx.baseUrl).href;\n if (await isSafeUrl(abs)) resolved.push(abs);\n } catch {\n // skip malformed URLs\n }\n }\n\n const results = await Promise.all(resolved.map((url) => ctx.fetch({ url })));\n\n const broken = results.filter((r) => !isOk(r));\n\n if (broken.length > 0) {\n const topBroken = broken.slice(0, 10).map((r) => `${r.url} (${r.status})`).join(', ');\n const brokenSummary = broken.length > 10 ? `${topBroken} (+${broken.length - 10} more)` : topBroken;\n return this.fail(\n `${broken.length}/${links.length} link(s) are broken.`,\n 'All links return HTTP 200',\n `Broken: ${brokenSummary}`,\n {\n priority: 'high',\n description:\n 'Broken links in llms.txt cause AI agents to hit dead ends, wasting their context window and degrading user experience. Fix the URLs to point to valid pages or remove links to pages that no longer exist.',\n code: `- [Page Name](/correct-path): Description of the page`,\n },\n );\n }\n\n return this.pass(\n `All ${links.length} link(s) return HTTP 200.`,\n 'All links return HTTP 200',\n `${links.length}/${links.length} valid`,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\nimport type { FetchResult } from '../../fetcher';\n\nfunction isOk(result: FetchResult): boolean {\n return result.status === 200;\n}\n\nexport class LlmsFullTxtAudit extends Audit {\n static override meta: AuditMeta = {\n id: '1.6',\n category: 'content-discoverability',\n title: 'llms-full.txt present',\n failureTitle: 'llms-full.txt present',\n description:\n 'llms-full.txt provides the complete content of your site in a single file, allowing AI agents to ingest everything in one request instead of crawling page by page.',\n scoreDisplayMode: 'binary',\n weight: 1.0,\n defaultPriority: 'high',\n guidance: {\n impact:\n 'Without llms-full.txt, AI agents must crawl your site page by page, which is slow and often incomplete. This means AI assistants give shallow or outdated answers about your products and services.',\n fix: 'Create a /llms-full.txt file at your site root containing the full text content of all important pages in markdown format. Include headings, descriptions, and key details for each page.',\n code: '# Your Site Name\\n\\n> Full content version for AI agents.\\n\\n## Home\\nYour homepage content here...\\n\\n## About\\nYour about page content here...\\n\\n## Documentation\\nYour documentation content here...',\n effort: 'moderate',\n docsUrl: 'https://llmstxt.org/',\n tags: ['llms-txt', 'discoverability'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const result = ctx.rootFiles['/llms-full.txt'];\n\n if (!result || !isOk(result)) {\n return this.fail(\n 'No llms-full.txt file found at the site root.',\n 'GET /llms-full.txt returns 200',\n result ? `HTTP ${result.status}` : 'No response',\n {\n priority: 'high',\n description:\n 'llms-full.txt provides the complete content of your site in a single file, allowing AI agents to ingest everything in one request instead of crawling page by page. This dramatically improves response quality when users ask about your site.',\n code: `# Your Site Name\\n\\n> Full content version for AI agents.\\n\\n## Home\\nYour homepage content here...\\n\\n## About\\nYour about page content here...\\n\\n## Documentation\\nYour documentation content here...`,\n docsUrl: 'https://llmstxt.org/',\n },\n );\n }\n\n return this.pass(\n 'llms-full.txt exists and returns HTTP 200.',\n 'HTTP 200',\n `HTTP ${result.status}`,\n );\n }\n}\n","import * as cheerio from 'cheerio';\nimport type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\nimport type { FetchResult } from '../../fetcher';\n\nfunction isOk(result: FetchResult): boolean {\n return result.status === 200;\n}\n\n/** Try to find the sitemap FetchResult from rootFiles, checking /sitemap.xml first then /sitemap-index.xml */\nfunction getSitemapResult(ctx: CheckContext): FetchResult | null {\n const sitemap = ctx.rootFiles['/sitemap.xml'];\n if (sitemap && isOk(sitemap)) return sitemap;\n const index = ctx.rootFiles['/sitemap-index.xml'];\n if (index && isOk(index)) return index;\n return null;\n}\n\nexport class SitemapExistsAudit extends Audit {\n static override meta: AuditMeta = {\n id: '1.7',\n category: 'content-discoverability',\n title: 'sitemap.xml exists',\n failureTitle: 'sitemap.xml exists',\n description:\n 'AI crawlers use your sitemap to discover all pages without following links. Without it, pages may never be indexed by AI search engines.',\n scoreDisplayMode: 'binary',\n weight: 1.0,\n defaultPriority: 'critical',\n guidance: {\n impact:\n 'Without a sitemap, AI crawlers must discover your pages solely through link-following, which is slow and incomplete. Pages deep in your site hierarchy may never be found, meaning AI search engines like Perplexity and ChatGPT Browse cannot surface your full content.',\n fix: 'Create a sitemap.xml at your site root containing all important pages. Use a <urlset> with <url> entries for each page, including <loc> and <lastmod>. Most frameworks (Next.js, WordPress, etc.) can auto-generate sitemaps.',\n code: '<?xml version=\"1.0\" encoding=\"UTF-8\"?>\\n<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\\n <url>\\n <loc>https://yoursite.com/</loc>\\n <lastmod>2026-01-01</lastmod>\\n <priority>1.0</priority>\\n </url>\\n</urlset>',\n effort: 'easy',\n docsUrl: 'https://www.sitemaps.org/protocol.html',\n tags: ['sitemap', 'seo', 'discoverability'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const sitemapResult = getSitemapResult(ctx);\n\n if (!sitemapResult) {\n return this.fail(\n 'No XML sitemap found at /sitemap.xml or /sitemap-index.xml.',\n 'HTTP 200 with valid XML containing <urlset> or <sitemapindex>',\n 'Not found at either path',\n {\n priority: 'critical',\n description:\n 'AI crawlers use your sitemap to discover all pages without following links. Without it, pages may never be indexed by AI search engines like Perplexity or ChatGPT Browse.',\n code: `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\\n<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\\n <url>\\n <loc>https://yoursite.com/</loc>\\n <lastmod>2026-01-01</lastmod>\\n <priority>1.0</priority>\\n </url>\\n</urlset>`,\n },\n );\n }\n\n const $ = cheerio.load(sitemapResult.body, { xmlMode: true });\n const hasUrlset = $('urlset').length > 0;\n const hasSitemapindex = $('sitemapindex').length > 0;\n\n if (!hasUrlset && !hasSitemapindex) {\n return this.fail(\n 'Sitemap file found but does not contain valid <urlset> or <sitemapindex>.',\n 'Valid XML with <urlset> or <sitemapindex>',\n 'No <urlset> or <sitemapindex> found in response',\n {\n priority: 'critical',\n description:\n 'Your sitemap.xml file exists but lacks the required XML structure. AI crawlers cannot parse it without a valid <urlset> or <sitemapindex> root element. Ensure the file is well-formed XML.',\n code: `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\\n<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\\n <url>\\n <loc>https://yoursite.com/</loc>\\n <lastmod>2026-01-01</lastmod>\\n </url>\\n</urlset>`,\n },\n );\n }\n\n return this.pass(\n 'XML sitemap exists with valid structure.',\n 'Valid <urlset> or <sitemapindex>',\n hasUrlset ? '<urlset> found' : '<sitemapindex> found',\n );\n }\n}\n","import * as cheerio from 'cheerio';\nimport type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\nimport type { FetchResult } from '../../fetcher';\n\nfunction isOk(result: FetchResult): boolean {\n return result.status === 200;\n}\n\n/** Try to find the sitemap FetchResult from rootFiles, checking /sitemap.xml first then /sitemap-index.xml */\nfunction getSitemapResult(ctx: CheckContext): FetchResult | null {\n const sitemap = ctx.rootFiles['/sitemap.xml'];\n if (sitemap && isOk(sitemap)) return sitemap;\n const index = ctx.rootFiles['/sitemap-index.xml'];\n if (index && isOk(index)) return index;\n return null;\n}\n\nexport class SitemapKeyPagesAudit extends Audit {\n static override meta: AuditMeta = {\n id: '1.8',\n category: 'content-discoverability',\n title: 'Sitemap includes all key pages',\n failureTitle: 'Sitemap includes all key pages',\n description:\n 'The sitemap should include all scanned pages so AI crawlers can discover your full site content.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'Pages missing from your sitemap may not be discovered by AI crawlers, even if they exist on your site. This means important content -- product pages, documentation, blog posts -- could be absent from AI search results.',\n fix: 'Ensure your sitemap.xml includes all important pages. Compare your sitemap against your actual site pages and add any missing URLs. Configure your CMS or build tool to auto-include new pages in the sitemap.',\n code: '<url>\\n <loc>https://yoursite.com/missing-page</loc>\\n <lastmod>2026-01-01</lastmod>\\n</url>',\n effort: 'easy',\n docsUrl: 'https://www.sitemaps.org/protocol.html',\n tags: ['sitemap', 'seo', 'discoverability'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const sitemapResult = getSitemapResult(ctx);\n\n if (!sitemapResult) {\n return this.fail(\n 'No sitemap found; cannot check key page coverage.',\n 'All scanned pages appear in sitemap',\n 'Sitemap not found',\n {\n priority: 'critical',\n description:\n 'First, create your sitemap.xml file (see check 1.7). The sitemap should list all your important pages so AI crawlers can discover them.',\n code: `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\\n<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\\n <url>\\n <loc>https://yoursite.com/</loc>\\n <lastmod>2026-01-01</lastmod>\\n </url>\\n</urlset>`,\n },\n );\n }\n\n const $ = cheerio.load(sitemapResult.body, { xmlMode: true });\n\n // Handle sitemap index files (<sitemapindex>)\n const isSitemapIndex = $('sitemapindex').length > 0 || $('sitemap > loc').length > 0;\n if (isSitemapIndex) {\n const subSitemaps: string[] = [];\n $('sitemap > loc').each((_, el) => {\n const loc = $(el).text().trim();\n if (loc) subSitemaps.push(loc);\n });\n return this.pass(\n `Sitemap index file found linking to ${subSitemaps.length} sub-sitemap(s).`,\n 'All scanned pages appear in sitemap or sitemap index',\n `Sitemap Index (${subSitemaps.length} sub-sitemaps)`,\n );\n }\n\n const sitemapUrls = new Set<string>();\n $('url > loc').each((_, el) => {\n const loc = $(el).text().trim();\n if (loc) sitemapUrls.add(loc);\n });\n\n if (sitemapUrls.size === 0) {\n return this.warn(\n 'Sitemap has no <url> entries.',\n 'All scanned pages appear in sitemap',\n 'No <url> entries',\n {\n priority: 'high',\n description:\n 'Your sitemap exists but contains no <url> entries. Add at least your main pages so AI crawlers can discover them.',\n code: `<url>\\n <loc>https://yoursite.com/</loc>\\n <lastmod>2026-01-01</lastmod>\\n</url>`,\n },\n );\n }\n\n const missing: string[] = [];\n for (const page of ctx.pages) {\n const pageUrl = page.url;\n const variants = [pageUrl, pageUrl.replace(/\\/$/, ''), pageUrl + '/'];\n const inSitemap = variants.some((v) => sitemapUrls.has(v));\n if (!inSitemap) {\n missing.push(pageUrl);\n }\n }\n\n if (missing.length > 0) {\n const ratio = missing.length / ctx.pages.length;\n if (ratio > 0.5) {\n return this.fail(\n `${missing.length}/${ctx.pages.length} scanned page(s) missing from sitemap.`,\n 'All scanned pages appear in sitemap',\n `Missing: ${missing.slice(0, 5).join(', ')}${missing.length > 5 ? ` (+${missing.length - 5} more)` : ''}`,\n {\n priority: 'medium',\n description:\n 'Many of your scanned pages are not listed in the sitemap. AI crawlers rely on the sitemap to discover pages. Add all important pages to ensure complete indexing.',\n code: `<url>\\n <loc>https://yoursite.com/missing-page</loc>\\n <lastmod>2026-01-01</lastmod>\\n</url>`,\n },\n );\n }\n return this.warn(\n `${missing.length}/${ctx.pages.length} scanned page(s) missing from sitemap.`,\n 'All scanned pages appear in sitemap',\n `Missing: ${missing.slice(0, 5).join(', ')}${missing.length > 5 ? ` (+${missing.length - 5} more)` : ''}`,\n {\n priority: 'low',\n description:\n 'Some scanned pages are not listed in the sitemap. Adding them helps AI crawlers discover all your content.',\n code: `<url>\\n <loc>https://yoursite.com/missing-page</loc>\\n <lastmod>2026-01-01</lastmod>\\n</url>`,\n },\n );\n }\n\n return this.pass(\n `All ${ctx.pages.length} scanned page(s) found in the sitemap.`,\n 'All scanned pages appear in sitemap',\n `${ctx.pages.length} page(s) found`,\n );\n }\n}\n","import * as cheerio from 'cheerio';\nimport type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\nimport type { FetchResult } from '../../fetcher';\n\nfunction isOk(result: FetchResult): boolean {\n return result.status === 200;\n}\n\n/** Try to find the sitemap FetchResult from rootFiles, checking /sitemap.xml first then /sitemap-index.xml */\nfunction getSitemapResult(ctx: CheckContext): FetchResult | null {\n const sitemap = ctx.rootFiles['/sitemap.xml'];\n if (sitemap && isOk(sitemap)) return sitemap;\n const index = ctx.rootFiles['/sitemap-index.xml'];\n if (index && isOk(index)) return index;\n return null;\n}\n\nexport class SitemapAbsoluteUrlsAudit extends Audit {\n static override meta: AuditMeta = {\n id: '1.9',\n category: 'content-discoverability',\n title: 'Sitemap uses absolute URLs',\n failureTitle: 'Sitemap uses absolute URLs',\n description:\n 'Sitemap URLs must be absolute (starting with https://) so AI crawlers can resolve them without ambiguity.',\n scoreDisplayMode: 'binary',\n weight: 1.0,\n defaultPriority: 'high',\n guidance: {\n impact:\n 'Relative URLs in your sitemap cannot be resolved by AI crawlers, causing them to silently skip those pages. Any page listed with a relative URL is effectively invisible to AI search engines.',\n fix: 'Ensure every <loc> value in your sitemap.xml starts with the full protocol and domain (e.g., https://yoursite.com/page). Update your sitemap generator configuration to output absolute URLs.',\n code: '<!-- Correct: absolute URL -->\\n<url>\\n <loc>https://yoursite.com/page</loc>\\n</url>\\n\\n<!-- Wrong: relative URL -->\\n<url>\\n <loc>/page</loc>\\n</url>',\n effort: 'trivial',\n docsUrl: 'https://www.sitemaps.org/protocol.html',\n tags: ['sitemap', 'seo', 'discoverability'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const sitemapResult = getSitemapResult(ctx);\n\n if (!sitemapResult) {\n return this.fail(\n 'No sitemap found; cannot check URL format.',\n 'All <loc> values are absolute URLs',\n 'Sitemap not found',\n {\n priority: 'critical',\n description:\n 'First, create your sitemap.xml file (see check 1.7). All URLs in the sitemap must be absolute so AI crawlers can resolve them.',\n code: `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\\n<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\\n <url>\\n <loc>https://yoursite.com/page</loc>\\n </url>\\n</urlset>`,\n },\n );\n }\n\n const $ = cheerio.load(sitemapResult.body, { xmlMode: true });\n const locs: string[] = [];\n $('url > loc').each((_, el) => {\n const loc = $(el).text().trim();\n if (loc) locs.push(loc);\n });\n\n if (locs.length === 0) {\n return this.fail(\n 'Sitemap has no <loc> entries to check.',\n 'All <loc> values are absolute URLs',\n 'No <loc> entries found',\n {\n priority: 'high',\n description: 'Your sitemap has no <loc> entries. Add absolute URLs for all your pages.',\n code: `<url>\\n <loc>https://yoursite.com/page</loc>\\n</url>`,\n },\n );\n }\n\n const relative = locs.filter(\n (loc) => !loc.startsWith('http://') && !loc.startsWith('https://'),\n );\n\n if (relative.length > 0) {\n return this.fail(\n `${relative.length}/${locs.length} <loc> value(s) use relative URLs.`,\n 'All <loc> values are absolute URLs (https://...)',\n `Relative: ${relative.slice(0, 5).join(', ')}${relative.length > 5 ? ` (+${relative.length - 5} more)` : ''}`,\n {\n priority: 'high',\n description:\n 'Sitemap URLs must be absolute (starting with http:// or https://) per the sitemaps.org protocol. Relative URLs cannot be resolved by AI crawlers and will be ignored.',\n code: `<!-- Use absolute URLs -->\\n<url>\\n <loc>https://yoursite.com/page</loc>\\n</url>\\n\\n<!-- NOT relative URLs -->\\n<url>\\n <loc>/page</loc> <!-- WRONG -->\\n</url>`,\n },\n );\n }\n\n return this.pass(\n `All ${locs.length} <loc> value(s) use absolute URLs.`,\n 'All <loc> values are absolute URLs',\n `${locs.length} absolute URL(s)`,\n );\n }\n}\n","import * as cheerio from 'cheerio';\nimport type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\nimport type { FetchResult } from '../../fetcher';\n\nfunction isOk(result: FetchResult): boolean {\n return result.status === 200;\n}\n\n/** Try to find the sitemap FetchResult from rootFiles, checking /sitemap.xml first then /sitemap-index.xml */\nfunction getSitemapResult(ctx: CheckContext): FetchResult | null {\n const sitemap = ctx.rootFiles['/sitemap.xml'];\n if (sitemap && isOk(sitemap)) return sitemap;\n const index = ctx.rootFiles['/sitemap-index.xml'];\n if (index && isOk(index)) return index;\n return null;\n}\n\nexport class SitemapLastmodAudit extends Audit {\n static override meta: AuditMeta = {\n id: '1.10',\n category: 'content-discoverability',\n title: 'Sitemap has lastmod dates',\n failureTitle: 'Sitemap has lastmod dates',\n description:\n 'AI crawlers use <lastmod> to decide which pages to re-index and which to skip. Without these dates, crawlers must re-fetch every page on every visit.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'Without <lastmod> dates, AI crawlers must re-fetch every page on every visit because they cannot tell which pages have changed. This wastes crawl budget and delays indexing of your freshest content.',\n fix: 'Add accurate <lastmod> dates to every <url> entry in your sitemap.xml. Update the date whenever the page content actually changes. Use ISO 8601 format (YYYY-MM-DD or full datetime).',\n code: '<url>\\n <loc>https://yoursite.com/page</loc>\\n <lastmod>2026-01-15</lastmod>\\n</url>',\n effort: 'easy',\n docsUrl: 'https://www.sitemaps.org/protocol.html',\n tags: ['sitemap', 'seo', 'discoverability'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const sitemapResult = getSitemapResult(ctx);\n\n if (!sitemapResult) {\n return this.fail(\n 'No sitemap found; cannot check lastmod.',\n 'At least 80% of <url> entries have <lastmod>',\n 'Sitemap not found',\n {\n priority: 'critical',\n description:\n 'First, create your sitemap.xml file (see check 1.7). The <lastmod> dates help AI crawlers prioritize fresh content and skip pages they have already indexed.',\n code: `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\\n<urlset xmlns=\"http://www.sitemaps.org/schemas/sitemap/0.9\">\\n <url>\\n <loc>https://yoursite.com/</loc>\\n <lastmod>2026-01-01</lastmod>\\n <priority>1.0</priority>\\n </url>\\n</urlset>`,\n },\n );\n }\n\n const $ = cheerio.load(sitemapResult.body, { xmlMode: true });\n const urls = $('url');\n const total = urls.length;\n\n if (total === 0) {\n return this.warn(\n 'Sitemap has no <url> entries.',\n 'At least 80% with <lastmod>',\n 'No <url> entries',\n {\n priority: 'high',\n description:\n 'Your sitemap exists but contains no <url> entries. Add at least your main pages so AI crawlers can discover them.',\n code: `<url>\\n <loc>https://yoursite.com/</loc>\\n <lastmod>2026-01-01</lastmod>\\n</url>`,\n },\n );\n }\n\n let withLastmod = 0;\n urls.each((_, el) => {\n if ($(el).find('lastmod').length > 0) withLastmod++;\n });\n\n const ratio = withLastmod / total;\n\n if (ratio < 0.8) {\n return this.fail(\n `Only ${Math.round(ratio * 100)}% of URL entries have <lastmod> (${withLastmod}/${total}).`,\n 'At least 80% of <url> entries have <lastmod>',\n `${withLastmod}/${total} (${Math.round(ratio * 100)}%)`,\n {\n priority: 'medium',\n description:\n 'AI crawlers use <lastmod> to decide which pages to re-index and which to skip. Without these dates, crawlers must re-fetch every page on every visit, wasting bandwidth and slowing indexing.',\n code: `<url>\\n <loc>https://yoursite.com/page</loc>\\n <lastmod>2026-01-15</lastmod>\\n</url>`,\n },\n );\n }\n\n return this.pass(\n `${Math.round(ratio * 100)}% of URL entries have <lastmod>.`,\n '>= 80% with <lastmod>',\n `${withLastmod}/${total} (${Math.round(ratio * 100)}%)`,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\nimport type { FetchResult } from '../../fetcher';\n\nfunction isOk(result: FetchResult): boolean {\n return result.status === 200;\n}\n\n/** Find RSS/Atom feed result -- check head links on pages first, then root file paths */\nasync function findFeedResult(\n ctx: CheckContext,\n): Promise<{ result: FetchResult; url: string } | null> {\n // Check <link rel=\"alternate\"> in page heads\n for (const page of ctx.pages) {\n for (const link of page.headLinks) {\n if (\n link.rel === 'alternate' &&\n (link.type === 'application/rss+xml' || link.type === 'application/atom+xml') &&\n link.href\n ) {\n let feedUrl = link.href;\n if (feedUrl.startsWith('/')) feedUrl = `${ctx.baseUrl}${feedUrl}`;\n const result = await ctx.fetch({ url: feedUrl });\n if (isOk(result)) return { result, url: feedUrl };\n }\n }\n }\n\n // Fall back to well-known paths\n const paths = ['/rss.xml', '/feed.xml', '/atom.xml'];\n for (const path of paths) {\n const rootResult = ctx.rootFiles[path];\n if (rootResult && isOk(rootResult)) {\n return { result: rootResult, url: `${ctx.baseUrl}${path}` };\n }\n }\n\n // Try /atom.xml explicitly since it may not be in rootFiles\n const atomResult = await ctx.fetch({ url: `${ctx.baseUrl}/atom.xml` });\n if (isOk(atomResult)) return { result: atomResult, url: `${ctx.baseUrl}/atom.xml` };\n\n return null;\n}\n\nexport class RssFeedAudit extends Audit {\n static override meta: AuditMeta = {\n id: '1.11',\n category: 'content-discoverability',\n title: 'RSS/Atom feed link present',\n failureTitle: 'RSS/Atom feed link present',\n description:\n 'RSS/Atom feeds let AI agents track new and updated content without re-crawling your entire site.',\n scoreDisplayMode: 'binary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'Without an RSS/Atom feed, AI agents have no efficient way to track new and updated content on your site. They must re-crawl your entire site to find changes, which means your latest posts and pages may take much longer to appear in AI search results.',\n fix: 'Create an RSS or Atom feed and link to it in your HTML <head> with a <link rel=\"alternate\"> tag. Most frameworks and CMS platforms can auto-generate feeds. Place the feed at a well-known path like /rss.xml or /feed.xml.',\n code: '<!-- Add to your HTML <head> -->\\n<link rel=\"alternate\" type=\"application/rss+xml\" title=\"Your Site Feed\" href=\"/rss.xml\" />\\n\\n<!-- Example /rss.xml -->\\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\\n<rss version=\"2.0\">\\n <channel>\\n <title>Your Site</title>\\n <link>https://yoursite.com</link>\\n <description>Site description</description>\\n <item>\\n <title>Article Title</title>\\n <link>https://yoursite.com/article</link>\\n <description>Article summary...</description>\\n </item>\\n </channel>\\n</rss>',\n effort: 'moderate',\n tags: ['rss', 'content-feed', 'discoverability'],\n },\n };\n\n async audit(ctx: CheckContext): Promise<AuditResult> {\n const feed = await findFeedResult(ctx);\n\n if (!feed) {\n return this.fail(\n 'No RSS or Atom feed found via head links or common paths (/rss.xml, /feed.xml, /atom.xml).',\n 'At least one feed returns HTTP 200 with valid XML',\n 'No feed found',\n {\n priority: 'medium',\n description:\n 'RSS/Atom feeds let AI agents track new and updated content without re-crawling your entire site. Agents like Perplexity and ChatGPT Browse use feeds to stay current with your latest posts and pages.',\n code: `<!-- Add to your HTML <head> -->\\n<link rel=\"alternate\" type=\"application/rss+xml\" title=\"Your Site Feed\" href=\"/rss.xml\" />\\n\\n<!-- Example /rss.xml -->\\n<?xml version=\"1.0\" encoding=\"UTF-8\"?>\\n<rss version=\"2.0\">\\n <channel>\\n <title>Your Site</title>\\n <link>https://yoursite.com</link>\\n <description>Site description</description>\\n <item>\\n <title>Article Title</title>\\n <link>https://yoursite.com/article</link>\\n <description>Article summary...</description>\\n </item>\\n </channel>\\n</rss>`,\n },\n );\n }\n\n return this.pass(\n `RSS/Atom feed found at ${feed.url}.`,\n 'Feed returns HTTP 200',\n `HTTP 200 at ${feed.url}`,\n );\n }\n}\n","import * as cheerio from 'cheerio';\nimport type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\nimport type { FetchResult } from '../../fetcher';\n\nfunction isOk(result: FetchResult): boolean {\n return result.status === 200;\n}\n\n/** Find RSS/Atom feed result -- check head links on pages first, then root file paths */\nasync function findFeedResult(\n ctx: CheckContext,\n): Promise<{ result: FetchResult; url: string } | null> {\n // Check <link rel=\"alternate\"> in page heads\n for (const page of ctx.pages) {\n for (const link of page.headLinks) {\n if (\n link.rel === 'alternate' &&\n (link.type === 'application/rss+xml' || link.type === 'application/atom+xml') &&\n link.href\n ) {\n let feedUrl = link.href;\n if (feedUrl.startsWith('/')) feedUrl = `${ctx.baseUrl}${feedUrl}`;\n const result = await ctx.fetch({ url: feedUrl });\n if (isOk(result)) return { result, url: feedUrl };\n }\n }\n }\n\n // Fall back to well-known paths\n const paths = ['/rss.xml', '/feed.xml', '/atom.xml'];\n for (const path of paths) {\n const rootResult = ctx.rootFiles[path];\n if (rootResult && isOk(rootResult)) {\n return { result: rootResult, url: `${ctx.baseUrl}${path}` };\n }\n }\n\n // Try /atom.xml explicitly since it may not be in rootFiles\n const atomResult = await ctx.fetch({ url: `${ctx.baseUrl}/atom.xml` });\n if (isOk(atomResult)) return { result: atomResult, url: `${ctx.baseUrl}/atom.xml` };\n\n return null;\n}\n\nexport class RssFeedContentAudit extends Audit {\n static override meta: AuditMeta = {\n id: '1.12',\n category: 'content-discoverability',\n title: 'RSS feed content complete',\n failureTitle: 'RSS feed content complete',\n description:\n 'Full-content feeds allow AI agents to index your articles without visiting each page, reducing crawl load and improving content quality in AI responses.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'Truncated RSS feed items force AI agents to visit each page individually, increasing crawl time and often resulting in incomplete indexing. Full-content feeds let agents ingest all your articles in a single request, producing richer AI-generated answers.',\n fix: 'Include full article content in each feed item using <content:encoded> (RSS) or <content> (Atom). Aim for more than 500 characters per item. Most CMS platforms have a setting to switch from excerpt to full-content feeds.',\n code: '<item>\\n <title>Article Title</title>\\n <link>https://yoursite.com/article</link>\\n <content:encoded><![CDATA[\\n <p>Full article content goes here. Include all paragraphs,\\n headings, and relevant details.</p>\\n ]]></content:encoded>\\n</item>',\n effort: 'easy',\n tags: ['rss', 'content-feed', 'discoverability'],\n },\n };\n\n async audit(ctx: CheckContext): Promise<AuditResult> {\n const feed = await findFeedResult(ctx);\n\n if (!feed) {\n return this.fail(\n 'No RSS feed found; cannot check content.',\n '<content:encoded> or <description> > 500 chars per item',\n 'No feed found',\n {\n priority: 'medium',\n description:\n 'First, create an RSS/Atom feed (see check 1.11). Full-content feeds allow AI agents to index your articles without visiting each page, reducing crawl load and improving content quality in AI responses.',\n code: `<item>\\n <title>Article Title</title>\\n <link>https://yoursite.com/article</link>\\n <content:encoded><![CDATA[\\n <p>Full article content goes here...</p>\\n ]]></content:encoded>\\n</item>`,\n },\n );\n }\n\n const $ = cheerio.load(feed.result.body, { xmlMode: true });\n const items = $('item, entry');\n const total = items.length;\n\n if (total === 0) {\n return this.warn(\n 'Feed has no items to check.',\n 'Items with full content',\n 'No items in feed',\n {\n priority: 'medium',\n description:\n 'Your feed exists but contains no items. Add your latest content entries so AI agents can discover and index them.',\n code: `<item>\\n <title>Article Title</title>\\n <link>https://yoursite.com/article</link>\\n <description>Article summary</description>\\n</item>`,\n },\n );\n }\n\n let withFullContent = 0;\n items.each((_, el) => {\n const contentEncoded = $(el).find('content\\\\:encoded, encoded').text();\n const description = $(el).find('description').text();\n const content = $(el).find('content').text();\n const longestContent = Math.max(contentEncoded.length, description.length, content.length);\n if (longestContent > 500) withFullContent++;\n });\n\n /* v8 ignore next -- total === 0 is handled by early return above; branch is unreachable */\n const ratio = total > 0 ? withFullContent / total : 0;\n\n if (ratio < 0.5) {\n return this.fail(\n `Only ${withFullContent}/${total} items have content > 500 characters.`,\n '<content:encoded> or <description> > 500 chars per item',\n `${withFullContent}/${total} items have substantial content`,\n {\n priority: 'medium',\n description:\n 'Truncated feed items force AI agents to visit each page individually. Including full content via <content:encoded> lets agents index your articles from the feed alone, improving speed and coverage.',\n code: `<item>\\n <title>Article Title</title>\\n <link>https://yoursite.com/article</link>\\n <content:encoded><![CDATA[\\n <p>Full article content goes here. Include all paragraphs,\\n headings, and relevant details.</p>\\n ]]></content:encoded>\\n</item>`,\n },\n );\n }\n\n if (ratio < 1.0) {\n return this.warn(\n `${withFullContent}/${total} items have full content (> 500 chars).`,\n 'All items with > 500 chars',\n `${withFullContent}/${total}`,\n {\n priority: 'low',\n description:\n 'Some feed items have truncated content. Expanding all items to full content helps AI agents provide complete answers without additional page fetches.',\n code: `<content:encoded><![CDATA[\\n <p>Full article content here...</p>\\n]]></content:encoded>`,\n },\n );\n }\n\n return this.pass(\n `All ${total} items have full content (> 500 chars).`,\n 'All items > 500 chars',\n `${total}/${total} items`,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class NoNoindexAudit extends Audit {\n static override meta: AuditMeta = {\n id: '1.13',\n category: 'content-discoverability',\n title: 'No noindex on homepage',\n failureTitle: 'No noindex on homepage',\n description:\n 'A noindex directive on your homepage prevents AI crawlers and search engines from indexing your most important page.',\n scoreDisplayMode: 'binary',\n weight: 1.0,\n defaultPriority: 'critical',\n guidance: {\n impact:\n 'A noindex directive on your homepage completely blocks AI crawlers and search engines from indexing your most important page. Your site becomes invisible in AI search results, causing total loss of organic AI-driven traffic.',\n fix: 'Remove the noindex directive from your homepage by updating the meta robots tag to \"index, follow\" and removing any X-Robots-Tag: noindex header from your server configuration.',\n code: '<!-- Remove noindex from homepage -->\\n<meta name=\"robots\" content=\"index, follow\" />',\n effort: 'trivial',\n docsUrl: 'https://developers.google.com/search/docs/crawling-indexing/robots-meta-tag',\n tags: ['robots', 'seo', 'discoverability'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const page = ctx.pages[0];\n if (!page) {\n return this.fail(\n 'No pages scanned.',\n 'Homepage has no noindex meta tag or X-Robots-Tag header',\n 'No pages scanned',\n {\n priority: 'critical',\n description: NoNoindexAudit.meta.description,\n },\n );\n }\n\n // Check meta robots tag\n const metaRobots = (page.meta['robots'] ?? '').toLowerCase();\n const hasMetaNoindex = metaRobots.includes('noindex');\n\n // Check X-Robots-Tag header\n const xRobotsTag = (page.fetchResult.headers['x-robots-tag'] ?? '').toLowerCase();\n const hasHeaderNoindex = xRobotsTag.includes('noindex');\n\n if (hasMetaNoindex || hasHeaderNoindex) {\n const sources: string[] = [];\n if (hasMetaNoindex) sources.push(`meta robots=\"${page.meta['robots']}\"`);\n if (hasHeaderNoindex)\n sources.push(`X-Robots-Tag: ${page.fetchResult.headers['x-robots-tag']}`);\n return this.fail(\n `Homepage has noindex directive: ${sources.join(', ')}.`,\n 'No noindex on homepage',\n sources.join('; '),\n {\n priority: 'critical',\n description:\n 'A noindex directive on your homepage blocks AI crawlers and search engines from indexing it. Remove the noindex from your homepage to ensure it appears in AI search results.',\n code: `<!-- Remove noindex from homepage -->\\n<meta name=\"robots\" content=\"index, follow\" />`,\n },\n page.url,\n );\n }\n\n return this.pass(\n 'Homepage has no noindex directive.',\n 'No noindex on homepage',\n 'No noindex found',\n page.url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class NoNofollowAudit extends Audit {\n static override meta: AuditMeta = {\n id: '1.14',\n category: 'content-discoverability',\n title: 'No nofollow on important links',\n failureTitle: 'No nofollow on important links',\n description:\n 'A site-wide nofollow directive prevents AI crawlers from following links to discover your content. Important internal links should be followable.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'high',\n guidance: {\n impact:\n 'A nofollow directive prevents AI crawlers from following links on your pages, effectively hiding all linked content from AI indexing. Your deeper pages become invisible to AI search engines, drastically reducing discoverability.',\n fix: 'Remove nofollow from your meta robots tag and X-Robots-Tag header on important pages. Use \"index, follow\" to allow full crawling. Reserve nofollow only for untrusted external links.',\n code: '<!-- Allow crawlers to follow links -->\\n<meta name=\"robots\" content=\"index, follow\" />',\n effort: 'trivial',\n docsUrl: 'https://developers.google.com/search/docs/crawling-indexing/robots-meta-tag',\n tags: ['robots', 'seo', 'discoverability'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n if (ctx.pages.length === 0) {\n return this.fail(\n 'No pages scanned.',\n 'No site-wide nofollow directives',\n 'No pages scanned',\n {\n priority: 'high',\n description: NoNofollowAudit.meta.description,\n },\n );\n }\n\n const pagesWithNofollow: string[] = [];\n\n for (const page of ctx.pages) {\n // Check meta robots tag for nofollow\n const metaRobots = (page.meta['robots'] ?? '').toLowerCase();\n const hasMetaNofollow = metaRobots.includes('nofollow');\n\n // Check X-Robots-Tag header for nofollow\n const xRobotsTag = (page.fetchResult.headers['x-robots-tag'] ?? '').toLowerCase();\n const hasHeaderNofollow = xRobotsTag.includes('nofollow');\n\n if (hasMetaNofollow || hasHeaderNofollow) {\n pagesWithNofollow.push(page.url);\n }\n }\n\n if (pagesWithNofollow.length === ctx.pages.length) {\n return this.fail(\n `All ${ctx.pages.length} scanned page(s) have nofollow directives.`,\n 'No site-wide nofollow directives',\n `${pagesWithNofollow.length}/${ctx.pages.length} pages have nofollow`,\n {\n priority: 'high',\n description:\n 'All your scanned pages have nofollow directives, which prevents AI crawlers from discovering linked content. Remove nofollow from important pages to allow full content discovery.',\n code: `<!-- Allow crawlers to follow links -->\\n<meta name=\"robots\" content=\"index, follow\" />`,\n },\n pagesWithNofollow[0],\n );\n }\n\n if (pagesWithNofollow.length > 0) {\n return this.warn(\n `${pagesWithNofollow.length}/${ctx.pages.length} page(s) have nofollow directives.`,\n 'No nofollow on important pages',\n `Nofollow on: ${pagesWithNofollow.slice(0, 5).join(', ')}${pagesWithNofollow.length > 5 ? ` (+${pagesWithNofollow.length - 5} more)` : ''}`,\n {\n priority: 'medium',\n description:\n 'Some pages have nofollow directives that prevent AI crawlers from following their links. Review whether these pages need nofollow or if it can be removed to improve content discovery.',\n code: `<!-- Allow crawlers to follow links -->\\n<meta name=\"robots\" content=\"index, follow\" />`,\n },\n pagesWithNofollow[0],\n );\n }\n\n return this.pass(\n 'No scanned pages have nofollow directives.',\n 'No nofollow on important pages',\n `${ctx.pages.length} page(s) checked`,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class InternalLinkingAudit extends Audit {\n static override meta: AuditMeta = {\n id: '1.15',\n category: 'content-discoverability',\n title: 'Internal linking structure',\n failureTitle: 'Internal linking structure',\n description:\n 'A strong internal linking structure helps AI crawlers discover and understand the relationships between your pages.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'Without internal links, AI crawlers cannot discover related pages or understand how your content is organized. This limits the depth of your site that gets indexed and weakens topical authority in AI search results.',\n fix: 'Add contextual internal links between related pages. Use descriptive anchor text that tells AI crawlers what the linked page is about. Aim for at least 3-5 internal links per page.',\n code: '<a href=\"/related-page\">Learn more about related topic</a>',\n effort: 'easy',\n tags: ['internal-links', 'seo', 'discoverability'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n if (ctx.pages.length === 0) {\n return this.fail(\n 'No pages scanned.',\n 'Pages have internal links to other pages on the same domain',\n 'No pages scanned',\n {\n priority: 'medium',\n description: InternalLinkingAudit.meta.description,\n },\n );\n }\n\n const domain = ctx.domain;\n let totalInternalLinks = 0;\n const pagesWithNoInternalLinks: string[] = [];\n\n for (const page of ctx.pages) {\n const $ = page.$;\n let pageInternalLinks = 0;\n\n $('a[href]').each((_, el) => {\n /* v8 ignore next -- a[href] selector guarantees attr is always a string */\n const href = $(el).attr('href') ?? '';\n try {\n const resolved = new URL(href, page.url);\n if (resolved.hostname === domain || resolved.hostname.endsWith(`.${domain}`)) {\n pageInternalLinks++;\n }\n } catch {\n // Relative URLs that fail to parse are likely internal\n if (\n href.startsWith('/') ||\n href.startsWith('#') ||\n href.startsWith('./') ||\n href.startsWith('../')\n ) {\n pageInternalLinks++;\n }\n }\n });\n\n totalInternalLinks += pageInternalLinks;\n if (pageInternalLinks === 0) {\n pagesWithNoInternalLinks.push(page.url);\n }\n }\n\n if (pagesWithNoInternalLinks.length === ctx.pages.length) {\n return this.fail(\n 'No scanned pages have internal links.',\n 'Pages have internal links to other pages',\n `${totalInternalLinks} internal links across ${ctx.pages.length} page(s)`,\n {\n priority: 'medium',\n description:\n 'None of your scanned pages contain internal links. Internal links help AI crawlers discover related content and understand your site structure. Add links between related pages.',\n code: `<a href=\"/related-page\">Related content</a>`,\n },\n pagesWithNoInternalLinks[0],\n );\n }\n\n if (pagesWithNoInternalLinks.length > 0) {\n return this.warn(\n `${pagesWithNoInternalLinks.length}/${ctx.pages.length} page(s) have no internal links.`,\n 'All pages have internal links',\n `Pages without links: ${pagesWithNoInternalLinks.slice(0, 5).join(', ')}${pagesWithNoInternalLinks.length > 5 ? ` (+${pagesWithNoInternalLinks.length - 5} more)` : ''}`,\n {\n priority: 'low',\n description:\n 'Some pages lack internal links, making them harder for AI crawlers to connect to the rest of your site. Add contextual links to related content.',\n code: `<a href=\"/related-page\">Related content</a>`,\n },\n pagesWithNoInternalLinks[0],\n );\n }\n\n const avgLinks = Math.round(totalInternalLinks / ctx.pages.length);\n return this.pass(\n `All ${ctx.pages.length} page(s) have internal links (avg ${avgLinks} per page).`,\n 'All pages have internal links',\n `${totalInternalLinks} total internal links`,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class NoRedirectChainsAudit extends Audit {\n static override meta: AuditMeta = {\n id: '1.16',\n category: 'content-discoverability',\n title: 'No redirect chains',\n failureTitle: 'No redirect chains',\n description:\n 'Redirect chains waste AI crawler budget and slow down content discovery. Each page should resolve in a single redirect at most.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'Redirect chains slow down AI crawlers and waste their limited crawl budget. Each extra redirect adds latency and increases the chance a crawler gives up before reaching the final page, leaving content unindexed.',\n fix: 'Update all internal links and sitemap entries to point directly to the final destination URL. Eliminate intermediate redirects by configuring your server to redirect directly from the old URL to the final URL in a single hop.',\n code: '<!-- Update links to use final URLs directly -->\\n<a href=\"https://yoursite.com/final-page\">Page</a>\\n\\n<!-- In sitemap.xml, use the final URL -->\\n<url>\\n <loc>https://yoursite.com/final-page</loc>\\n</url>',\n effort: 'easy',\n tags: ['redirects', 'performance', 'discoverability'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n if (ctx.pages.length === 0) {\n return this.fail(\n 'No pages scanned.',\n 'No redirect chains (URL equals finalUrl or single redirect)',\n 'No pages scanned',\n {\n priority: 'medium',\n description: NoRedirectChainsAudit.meta.description,\n },\n );\n }\n\n const redirected: Array<{ from: string; to: string }> = [];\n\n for (const page of ctx.pages) {\n const requestUrl = page.fetchResult.url;\n const finalUrl = page.fetchResult.finalUrl;\n if (requestUrl !== finalUrl) {\n redirected.push({ from: requestUrl, to: finalUrl });\n }\n }\n\n if (redirected.length === 0) {\n return this.pass(\n `All ${ctx.pages.length} page(s) resolve without redirects.`,\n 'No redirect chains',\n `${ctx.pages.length} page(s) with no redirects`,\n );\n }\n\n if (redirected.length > ctx.pages.length / 2) {\n return this.fail(\n `${redirected.length}/${ctx.pages.length} page(s) involve redirects.`,\n 'No redirect chains',\n `Redirected: ${redirected\n .slice(0, 5)\n .map((r) => `${r.from} -> ${r.to}`)\n .join(', ')}${redirected.length > 5 ? ` (+${redirected.length - 5} more)` : ''}`,\n {\n priority: 'medium',\n description:\n 'Many pages involve redirects, which slow down AI crawler discovery and waste crawl budget. Update internal links and sitemap entries to point directly to the final URLs.',\n code: `<!-- Update links to use final URLs directly -->\\n<a href=\"https://yoursite.com/final-page\">Page</a>\\n\\n<!-- Update sitemap -->\\n<url>\\n <loc>https://yoursite.com/final-page</loc>\\n</url>`,\n },\n redirected[0]?.from,\n );\n }\n\n return this.warn(\n `${redirected.length}/${ctx.pages.length} page(s) involve redirects.`,\n 'No redirect chains',\n `Redirected: ${redirected\n .slice(0, 5)\n .map((r) => `${r.from} -> ${r.to}`)\n .join(', ')}${redirected.length > 5 ? ` (+${redirected.length - 5} more)` : ''}`,\n {\n priority: 'low',\n description:\n 'Some pages involve redirects. Update internal links and sitemap entries to point to the final URLs to avoid unnecessary redirects for AI crawlers.',\n code: `<!-- Point directly to the final URL -->\\n<a href=\"https://yoursite.com/final-page\">Page</a>`,\n },\n redirected[0]?.from,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class CanonicalLinksAudit extends Audit {\n static override meta: AuditMeta = {\n id: '1.17',\n category: 'content-discoverability',\n title: 'Canonical links present',\n failureTitle: 'Canonical links present',\n description:\n 'Canonical link tags tell AI crawlers which URL is the authoritative version of a page, preventing duplicate content issues.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'Without canonical tags, AI crawlers may index duplicate versions of your pages (www vs non-www, HTTP vs HTTPS, trailing slash variants), diluting your content authority and causing inconsistent answers in AI search results.',\n fix: 'Add a <link rel=\"canonical\"> tag to the <head> of every page pointing to the preferred URL. Ensure canonical URLs are absolute and consistent across all page variants.',\n code: '<link rel=\"canonical\" href=\"https://yoursite.com/page\" />',\n effort: 'easy',\n docsUrl:\n 'https://developers.google.com/search/docs/crawling-indexing/consolidate-duplicate-urls',\n tags: ['canonical', 'seo', 'discoverability'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n if (ctx.pages.length === 0) {\n return this.fail(\n 'No pages scanned.',\n 'All pages have <link rel=\"canonical\">',\n 'No pages scanned',\n {\n priority: 'medium',\n description: CanonicalLinksAudit.meta.description,\n },\n );\n }\n\n const pagesWithoutCanonical: string[] = [];\n\n for (const page of ctx.pages) {\n const $ = page.$;\n const canonical = $('link[rel=\"canonical\"]').attr('href');\n if (!canonical) {\n pagesWithoutCanonical.push(page.url);\n }\n }\n\n if (pagesWithoutCanonical.length === ctx.pages.length) {\n return this.fail(\n 'No scanned pages have canonical link tags.',\n 'All pages have <link rel=\"canonical\">',\n `${pagesWithoutCanonical.length}/${ctx.pages.length} pages missing canonical`,\n {\n priority: 'medium',\n description:\n 'None of your scanned pages have canonical link tags. Without them, AI crawlers may index duplicate versions of your pages (www vs non-www, HTTP vs HTTPS, with/without trailing slash).',\n code: `<link rel=\"canonical\" href=\"https://yoursite.com/page\" />`,\n },\n pagesWithoutCanonical[0],\n );\n }\n\n if (pagesWithoutCanonical.length > 0) {\n return this.warn(\n `${pagesWithoutCanonical.length}/${ctx.pages.length} page(s) missing canonical link tags.`,\n 'All pages have <link rel=\"canonical\">',\n `Missing on: ${pagesWithoutCanonical.slice(0, 5).join(', ')}${pagesWithoutCanonical.length > 5 ? ` (+${pagesWithoutCanonical.length - 5} more)` : ''}`,\n {\n priority: 'low',\n description:\n 'Some pages are missing canonical link tags. Adding them prevents AI crawlers from indexing duplicate versions of your content.',\n code: `<link rel=\"canonical\" href=\"https://yoursite.com/page\" />`,\n },\n pagesWithoutCanonical[0],\n );\n }\n\n return this.pass(\n `All ${ctx.pages.length} page(s) have canonical link tags.`,\n 'All pages have <link rel=\"canonical\">',\n `${ctx.pages.length} page(s) with canonical`,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class MobileFriendlyAudit extends Audit {\n static override meta: AuditMeta = {\n id: '1.18',\n category: 'content-discoverability',\n title: 'Mobile friendly',\n failureTitle: 'Mobile friendly',\n description:\n 'A viewport meta tag signals mobile-friendliness. AI crawlers may prioritize mobile-friendly content, and many AI-powered searches originate from mobile devices.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'AI crawlers and search engines may deprioritize pages without a viewport meta tag. Since many AI-powered searches originate from mobile devices, non-mobile-friendly pages rank lower and deliver a poor experience.',\n fix: 'Add a viewport meta tag to the <head> of every page. This is typically a one-line addition to your HTML template or layout component.',\n code: '<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />',\n effort: 'trivial',\n docsUrl: 'https://developer.mozilla.org/en-US/docs/Web/HTML/Viewport_meta_tag',\n tags: ['mobile', 'seo', 'discoverability'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n if (ctx.pages.length === 0) {\n return this.fail(\n 'No pages scanned.',\n 'Pages have <meta name=\"viewport\"> tag',\n 'No pages scanned',\n {\n priority: 'medium',\n description: MobileFriendlyAudit.meta.description,\n },\n );\n }\n\n const pagesWithoutViewport: string[] = [];\n\n for (const page of ctx.pages) {\n const viewport = page.meta['viewport'];\n if (!viewport) {\n pagesWithoutViewport.push(page.url);\n }\n }\n\n if (pagesWithoutViewport.length === ctx.pages.length) {\n return this.fail(\n 'No scanned pages have a viewport meta tag.',\n 'All pages have <meta name=\"viewport\">',\n `${pagesWithoutViewport.length}/${ctx.pages.length} pages missing viewport`,\n {\n priority: 'medium',\n description:\n 'None of your scanned pages have a viewport meta tag. Without it, pages are not mobile-friendly, which can negatively impact ranking in AI search results.',\n code: `<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />`,\n },\n pagesWithoutViewport[0],\n );\n }\n\n if (pagesWithoutViewport.length > 0) {\n return this.warn(\n `${pagesWithoutViewport.length}/${ctx.pages.length} page(s) missing viewport meta tag.`,\n 'All pages have <meta name=\"viewport\">',\n `Missing on: ${pagesWithoutViewport.slice(0, 5).join(', ')}${pagesWithoutViewport.length > 5 ? ` (+${pagesWithoutViewport.length - 5} more)` : ''}`,\n {\n priority: 'low',\n description:\n 'Some pages are missing the viewport meta tag. Adding it ensures they display correctly on mobile and are considered mobile-friendly by AI crawlers.',\n code: `<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" />`,\n },\n pagesWithoutViewport[0],\n );\n }\n\n return this.pass(\n `All ${ctx.pages.length} page(s) have a viewport meta tag.`,\n 'All pages have <meta name=\"viewport\">',\n `${ctx.pages.length} page(s) with viewport`,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\n/** Threshold in milliseconds for TTFB: fast <= 800ms, slow > 1800ms */\nconst FAST_TTFB_MS = 800;\nconst SLOW_TTFB_MS = 1800;\n\nexport class FastPageLoadAudit extends Audit {\n static override meta: AuditMeta = {\n id: '1.19',\n category: 'content-discoverability',\n title: 'Fast page load',\n failureTitle: 'Fast page load',\n description:\n 'AI crawlers have limited time budgets. Fast Time-to-First-Byte (TTFB) ensures crawlers can fetch more of your pages within their allotted time.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'AI crawlers operate on strict time budgets. Slow Time-to-First-Byte (TTFB) means crawlers index fewer of your pages per session, leaving content undiscovered and reducing your visibility in AI-powered search results.',\n fix: 'Optimize server response times by enabling caching (Redis, Varnish), deploying a CDN (Cloudflare, Fastly), reducing server-side computation, and enabling HTTP/2 or HTTP/3. Target TTFB under 800ms for all pages.',\n code: '# Potential optimizations:\\n# - Enable server-side caching (Redis, Varnish)\\n# - Use a CDN (Cloudflare, Fastly, Vercel Edge)\\n# - Optimize database queries and indexes\\n# - Enable HTTP/2 or HTTP/3\\n# - Use static generation where possible',\n effort: 'moderate',\n tags: ['performance', 'crawl-budget', 'discoverability'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n if (ctx.pages.length === 0) {\n return this.fail('No pages scanned.', `TTFB <= ${FAST_TTFB_MS}ms`, 'No pages scanned', {\n priority: 'medium',\n description: FastPageLoadAudit.meta.description,\n });\n }\n\n const slowPages: Array<{ url: string; ttfb: number }> = [];\n\n for (const page of ctx.pages) {\n if (page.fetchResult.ttfbMs > SLOW_TTFB_MS) {\n slowPages.push({ url: page.url, ttfb: page.fetchResult.ttfbMs });\n }\n }\n\n const avgTtfb = Math.round(\n ctx.pages.reduce((sum, p) => sum + p.fetchResult.ttfbMs, 0) / ctx.pages.length,\n );\n\n if (slowPages.length > 0) {\n return this.fail(\n `${slowPages.length}/${ctx.pages.length} page(s) have TTFB > ${SLOW_TTFB_MS}ms (avg ${avgTtfb}ms).`,\n `TTFB <= ${FAST_TTFB_MS}ms`,\n `Slow pages: ${slowPages\n .slice(0, 5)\n .map((p) => `${p.url} (${p.ttfb}ms)`)\n .join(', ')}${slowPages.length > 5 ? ` (+${slowPages.length - 5} more)` : ''}`,\n {\n priority: 'medium',\n description:\n 'Some pages have very slow Time-to-First-Byte (TTFB), which may cause AI crawlers to time out or skip them. Optimize server response times through caching, CDN usage, or reducing server-side processing.',\n code: `# Potential optimizations:\\n# - Enable server-side caching\\n# - Use a CDN (Cloudflare, Fastly)\\n# - Optimize database queries\\n# - Enable HTTP/2 or HTTP/3`,\n },\n slowPages[0]?.url,\n );\n }\n\n if (avgTtfb > FAST_TTFB_MS) {\n return this.warn(\n `Average TTFB is ${avgTtfb}ms across ${ctx.pages.length} page(s).`,\n `TTFB <= ${FAST_TTFB_MS}ms`,\n `Average ${avgTtfb}ms`,\n {\n priority: 'low',\n description:\n 'Average TTFB is above the ideal threshold. Faster responses help AI crawlers index more pages within their time budget.',\n code: `# Potential optimizations:\\n# - Enable server-side caching\\n# - Use a CDN\\n# - Optimize server-side rendering`,\n },\n );\n }\n\n return this.pass(\n `Average TTFB is ${avgTtfb}ms across ${ctx.pages.length} page(s).`,\n `TTFB <= ${FAST_TTFB_MS}ms`,\n `Average ${avgTtfb}ms`,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\nimport type { FetchResult } from '../../fetcher';\n\nfunction isOk(result: FetchResult): boolean {\n return result.status === 200;\n}\n\nexport class NoBrokenLinksAudit extends Audit {\n static override meta: AuditMeta = {\n id: '1.20',\n category: 'content-discoverability',\n title: 'No broken internal links',\n failureTitle: 'No broken internal links',\n description:\n 'Broken internal links create dead ends for AI crawlers and waste their limited crawl budget.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'high',\n guidance: {\n impact:\n \"Broken internal links waste AI crawlers' limited crawl budget by sending them to dead ends. This means fewer of your pages get indexed, and users asking AI about your site may encounter errors or missing information.\",\n fix: 'Audit all internal links and fix or remove any that return non-200 status codes. Update href values to point to the correct URLs, and set up redirects for pages that have moved.',\n code: '<!-- Fix broken links by updating the href -->\\n<a href=\"/correct-path\">Page title</a>\\n\\n<!-- Or set up a redirect for moved pages -->\\n<!-- In next.config.js -->\\nredirects: [{ source: \"/old-path\", destination: \"/new-path\", permanent: true }]',\n effort: 'easy',\n tags: ['broken-links', 'crawl-budget', 'discoverability'],\n },\n };\n\n async audit(ctx: CheckContext): Promise<AuditResult> {\n if (ctx.pages.length === 0) {\n return this.fail(\n 'No pages scanned.',\n 'All internal links return HTTP 200',\n 'No pages scanned',\n {\n priority: 'high',\n description: NoBrokenLinksAudit.meta.description,\n },\n );\n }\n\n const domain = ctx.domain;\n const internalUrls = new Set<string>();\n\n for (const page of ctx.pages) {\n const $ = page.$;\n $('a[href]').each((_, el) => {\n /* v8 ignore next -- a[href] selector guarantees attr is always a string */\n const href = $(el).attr('href') ?? '';\n try {\n const resolved = new URL(href, page.url);\n if (resolved.hostname === domain || resolved.hostname.endsWith(`.${domain}`)) {\n // Normalize: remove hash, keep path + query\n resolved.hash = '';\n internalUrls.add(resolved.href);\n }\n } catch {\n // Skip invalid URLs\n }\n });\n }\n\n if (internalUrls.size === 0) {\n return this.warn(\n 'No internal links found to validate.',\n 'All internal links return HTTP 200',\n 'No internal links found',\n {\n priority: 'medium',\n description:\n 'No internal links were found on the scanned pages. Add internal links between related pages to help AI crawlers discover your content.',\n code: `<a href=\"/related-page\">Related content</a>`,\n },\n );\n }\n\n // Sample up to 20 internal links to avoid excessive fetching\n const urlsToCheck = Array.from(internalUrls).slice(0, 20);\n const results = await Promise.all(urlsToCheck.map((url) => ctx.fetch({ url })));\n\n const broken = results.filter((r) => !isOk(r));\n\n if (broken.length > 0) {\n const brokenUrls = broken.map((r) => `${r.url} (${r.status})`).join(', ');\n\n if (broken.length > urlsToCheck.length / 2) {\n return this.fail(\n `${broken.length}/${urlsToCheck.length} sampled internal link(s) are broken.`,\n 'All internal links return HTTP 200',\n `Broken: ${brokenUrls}`,\n {\n priority: 'high',\n description:\n 'Many internal links are broken, creating dead ends for AI crawlers. Fix or remove these links to ensure crawlers can navigate your site effectively.',\n code: `<!-- Fix broken links -->\\n<a href=\"/correct-path\">Page title</a>`,\n },\n );\n }\n\n return this.warn(\n `${broken.length}/${urlsToCheck.length} sampled internal link(s) are broken.`,\n 'All internal links return HTTP 200',\n `Broken: ${brokenUrls}`,\n {\n priority: 'medium',\n description:\n 'Some internal links are broken. Fix them to prevent AI crawlers from encountering dead ends.',\n code: `<!-- Fix broken links -->\\n<a href=\"/correct-path\">Page title</a>`,\n },\n );\n }\n\n return this.pass(\n `All ${urlsToCheck.length} sampled internal link(s) return HTTP 200.`,\n 'All internal links return HTTP 200',\n `${urlsToCheck.length} link(s) checked`,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\nimport type { FetchResult } from '../../fetcher';\n\nfunction isOk(result: FetchResult): boolean {\n return result.status === 200;\n}\n\nexport class NavigationJsonAudit extends Audit {\n static override meta: AuditMeta = {\n id: '1.21',\n category: 'content-discoverability',\n title: 'navigation.json present',\n failureTitle: 'navigation.json present',\n description:\n 'A navigation.json file gives AI agents a machine-readable map of your site hierarchy, helping them navigate your site like a human would.',\n scoreDisplayMode: 'binary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'Without a machine-readable navigation structure, AI agents must infer your site hierarchy from HTML parsing, which is error-prone and incomplete. A navigation.json gives agents a clear map of your site, enabling accurate multi-step browsing.',\n fix: 'Create a /navigation.json file at your site root with a JSON structure representing your site menu hierarchy. Include labels, URLs, and nested children for submenus.',\n code: '{\\n \"name\": \"Your Site\",\\n \"items\": [\\n { \"label\": \"Home\", \"url\": \"/\" },\\n { \"label\": \"Products\", \"url\": \"/products\", \"children\": [\\n { \"label\": \"Product A\", \"url\": \"/products/a\" },\\n { \"label\": \"Product B\", \"url\": \"/products/b\" }\\n ]},\\n { \"label\": \"About\", \"url\": \"/about\" }\\n ]\\n}',\n effort: 'easy',\n tags: ['navigation', 'structured-data', 'discoverability'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const result = ctx.rootFiles['/navigation.json'];\n\n if (!result || !isOk(result)) {\n return this.fail(\n 'No navigation.json found at the site root.',\n 'GET /navigation.json returns 200 with valid JSON',\n result ? `HTTP ${result.status}` : 'No response',\n {\n priority: 'medium',\n description:\n 'A navigation.json file gives AI agents a machine-readable map of your site hierarchy. This helps agents navigate your site like a human would, following logical paths through menus and sections.',\n code: `{\\n \"name\": \"Your Site\",\\n \"items\": [\\n { \"label\": \"Home\", \"url\": \"/\" },\\n { \"label\": \"Products\", \"url\": \"/products\", \"children\": [\\n { \"label\": \"Product A\", \"url\": \"/products/a\" },\\n { \"label\": \"Product B\", \"url\": \"/products/b\" }\\n ]},\\n { \"label\": \"About\", \"url\": \"/about\" }\\n ]\\n}`,\n },\n );\n }\n\n try {\n JSON.parse(result.body);\n } catch {\n return this.fail(\n 'navigation.json exists but contains invalid JSON.',\n 'Valid JSON content',\n 'Invalid JSON',\n {\n priority: 'medium',\n description:\n 'Your navigation.json has invalid JSON syntax, so AI agents cannot parse it. Validate the JSON and fix any syntax errors (missing commas, unquoted keys, etc.).',\n code: `{\\n \"name\": \"Your Site\",\\n \"items\": [\\n { \"label\": \"Home\", \"url\": \"/\" },\\n { \"label\": \"About\", \"url\": \"/about\" }\\n ]\\n}`,\n },\n );\n }\n\n return this.pass(\n 'navigation.json exists with valid JSON.',\n 'HTTP 200 with valid JSON',\n 'Valid JSON',\n );\n }\n}\n","import * as cheerio from 'cheerio';\nimport type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\nimport type { FetchResult } from '../../fetcher';\nimport { extractMarkdownLinks } from '../../parser';\n\nfunction isOk(result: FetchResult): boolean {\n return result.status === 200;\n}\n\n/** Try to find the sitemap FetchResult from rootFiles, checking /sitemap.xml first then /sitemap-index.xml */\nfunction getSitemapResult(ctx: CheckContext): FetchResult | null {\n const sitemap = ctx.rootFiles['/sitemap.xml'];\n if (sitemap && isOk(sitemap)) return sitemap;\n const index = ctx.rootFiles['/sitemap-index.xml'];\n if (index && isOk(index)) return index;\n return null;\n}\n\nexport class NoOrphanPagesAudit extends Audit {\n static override meta: AuditMeta = {\n id: '1.22',\n category: 'content-discoverability',\n title: 'No orphan pages',\n failureTitle: 'No orphan pages',\n description:\n 'Orphan pages are not listed in your sitemap or llms.txt, so AI crawlers may never discover them.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'Orphan pages are not referenced in your sitemap or llms.txt, so AI crawlers may never discover them. This means potentially valuable content -- product pages, blog posts, documentation -- remains invisible to AI-powered search.',\n fix: 'Add all important pages to your sitemap.xml and/or reference them in your llms.txt file. Run a crawl comparison periodically to catch pages that fall out of both indexes.',\n code: '<!-- Add to sitemap.xml -->\\n<url>\\n <loc>https://yoursite.com/orphan-page</loc>\\n <lastmod>2026-01-01</lastmod>\\n</url>\\n\\n# Or add to llms.txt\\n- [Orphan Page](/orphan-page): Description of the page',\n effort: 'easy',\n tags: ['orphan-pages', 'sitemap', 'discoverability'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n // Collect all URLs listed in sitemap\n const sitemapUrls = new Set<string>();\n const sitemapResult = getSitemapResult(ctx);\n if (sitemapResult) {\n const $ = cheerio.load(sitemapResult.body, { xmlMode: true });\n $('url > loc, sitemap > loc, loc').each((_, el) => {\n const loc = $(el).text().trim();\n if (loc) {\n sitemapUrls.add(loc);\n try {\n const u = new URL(loc);\n u.search = '';\n u.hash = '';\n sitemapUrls.add(u.href);\n } catch {\n // ignore\n }\n }\n });\n }\n\n // Collect URLs listed in llms.txt\n const llmsUrls = new Set<string>();\n const llmsResult = ctx.rootFiles['/llms.txt'];\n if (llmsResult && isOk(llmsResult)) {\n const links = extractMarkdownLinks(llmsResult.body);\n for (const link of links) {\n try {\n const parsed = new URL(link.url, ctx.baseUrl);\n llmsUrls.add(parsed.href);\n parsed.search = '';\n parsed.hash = '';\n llmsUrls.add(parsed.href);\n } catch {\n // skip invalid URLs\n }\n }\n }\n\n if (sitemapUrls.size === 0 && llmsUrls.size === 0) {\n return this.warn(\n 'No sitemap or llms.txt links to compare against scanned pages.',\n 'All scanned pages appear in sitemap or llms.txt',\n 'No sitemap URLs or llms.txt links found',\n {\n priority: 'medium',\n description:\n 'Without a sitemap or llms.txt, AI crawlers have no reference list of your pages. Create at least one so we can verify all your pages are discoverable.',\n code: `Sitemap: https://yoursite.com/sitemap.xml`,\n },\n );\n }\n\n const orphans: string[] = [];\n for (const page of ctx.pages) {\n const pageUrl = page.url;\n let cleanUrl = pageUrl;\n try {\n const u = new URL(pageUrl);\n u.search = '';\n u.hash = '';\n cleanUrl = u.href;\n } catch {\n // keep pageUrl\n }\n\n // Normalize for comparison: try raw, clean, canonical with/without trailing slash\n const variants = [\n pageUrl,\n pageUrl.replace(/\\/$/, ''),\n pageUrl + '/',\n cleanUrl,\n cleanUrl.replace(/\\/$/, ''),\n cleanUrl + '/',\n ];\n\n const canonical = page.meta['canonical'] || page.meta['og:url'];\n if (canonical) {\n variants.push(canonical, canonical.replace(/\\/$/, ''), canonical + '/');\n }\n\n const inSitemap = variants.some((v) => sitemapUrls.has(v));\n const inLlms = variants.some((v) => llmsUrls.has(v));\n\n // Check if covered by a sub-sitemap pattern in a sitemapindex\n let inSitemapIndexPattern = false;\n if (sitemapResult && (sitemapResult.body.includes('<sitemapindex') || sitemapResult.body.includes('<sitemap>'))) {\n try {\n const path = new URL(pageUrl).pathname.toLowerCase();\n if (\n (path.startsWith('/products') && sitemapResult.body.includes('sitemap_products')) ||\n (path.startsWith('/collections') && sitemapResult.body.includes('sitemap_collections')) ||\n (path.startsWith('/pages') && sitemapResult.body.includes('sitemap_pages')) ||\n (path.startsWith('/blogs') && sitemapResult.body.includes('sitemap_blogs')) ||\n (path.startsWith('/posts') && sitemapResult.body.includes('sitemap_posts')) ||\n (path.startsWith('/docs') && sitemapResult.body.includes('sitemap_docs'))\n ) {\n inSitemapIndexPattern = true;\n }\n } catch {\n // ignore\n }\n }\n\n if (!inSitemap && !inLlms && !inSitemapIndexPattern) {\n orphans.push(pageUrl);\n }\n }\n\n if (orphans.length > 0) {\n return this.fail(\n `${orphans.length} scanned page(s) not found in sitemap or llms.txt.`,\n 'All scanned pages appear in sitemap or llms.txt',\n `Orphan pages: ${orphans.slice(0, 5).join(', ')}${orphans.length > 5 ? ` (+${orphans.length - 5} more)` : ''}`,\n {\n priority: 'medium',\n description:\n 'Orphan pages are not listed in your sitemap or llms.txt, so AI crawlers may never discover them. Add these pages to your sitemap.xml or reference them in llms.txt to ensure complete coverage.',\n code: `<!-- Add to sitemap.xml -->\\n<url>\\n <loc>https://yoursite.com/orphan-page</loc>\\n <lastmod>2026-01-01</lastmod>\\n</url>`,\n },\n );\n }\n\n return this.pass(\n `All ${ctx.pages.length} scanned page(s) are in the sitemap or llms.txt.`,\n 'No orphan pages',\n `${ctx.pages.length} page(s) accounted for`,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class CommerceLinksAudit extends Audit {\n static override meta: AuditMeta = {\n id: '1.23',\n category: 'content-discoverability',\n title: 'Critical commerce links',\n failureTitle: 'Critical commerce links',\n description:\n 'AI agents must provide transparency on shipping and returns to help users make buying decisions. Finding and verifying these links is essential for \"Instant Checkout\" readiness.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'AI shopping agents cannot complete purchase recommendations without verifiable return, shipping, and seller information. Missing these links disqualifies your store from \"Instant Checkout\" flows and erodes buyer trust.',\n fix: 'Add clearly labeled links to your return policy, shipping information, and seller/contact pages in your site footer or navigation. Use descriptive anchor text like \"Return Policy\", \"Shipping & Delivery\", and \"About Us\".',\n code: '<footer>\\n <a href=\"/returns\">Return Policy</a>\\n <a href=\"/shipping\">Shipping & Delivery</a>\\n <a href=\"/about\">About Us</a>\\n</footer>',\n effort: 'easy',\n tags: ['commerce', 'trust', 'discoverability'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const page = ctx.pages[0];\n if (!page) return this.fail('No pages for analysis.', '', 'None');\n\n const $ = page.$;\n const links = $('a[href]')\n .map((_, el) => ({\n text: $(el).text().toLowerCase(),\n href: $(el).attr('href')?.toLowerCase() || '',\n }))\n .get();\n\n const policies: Record<string, boolean> = {\n return: false,\n shipping: false,\n seller: false,\n };\n\n for (const link of links) {\n if (link.href.includes('return') || link.text.includes('return policy'))\n policies.return = true;\n if (link.href.includes('shipping') || link.text.includes('delivery'))\n policies.shipping = true;\n if (\n link.href.includes('seller') ||\n link.text.includes('about us') ||\n link.href.includes('contact')\n )\n policies.seller = true;\n }\n\n const found = Object.entries(policies)\n .filter(([_, v]) => v)\n .map(([k]) => k);\n const missing = Object.entries(policies)\n .filter(([_, v]) => !v)\n .map(([k]) => k);\n\n if (missing.length === 0) {\n return this.pass(\n 'Found links for return policy, shipping, and seller info.',\n 'Links to return policy, shipping, and seller/contact pages.',\n 'All present',\n );\n }\n\n if (found.length > 0) {\n return this.warn(\n `Missing some critical commerce links: ${missing.join(', ')}.`,\n 'Links to return policy, shipping, and seller/contact pages.',\n `Found: ${found.join(', ')}`,\n {\n priority: 'medium',\n description:\n 'AI agents require easy access to shipping and return information to finalize transactions.',\n },\n );\n }\n\n return this.fail(\n 'Missing all critical commerce links (Return, Shipping, Seller).',\n 'Links to return policy, shipping, and seller/contact pages.',\n 'None found',\n {\n priority: 'medium',\n description:\n 'Provide clear, discoverable links to your policies in the footer to help AI agents process orders.',\n },\n );\n }\n}\n","// ── Types ─────────────────────────────────────────────────────\n\nexport interface RobotsTxtRule {\n type: 'allow' | 'disallow';\n path: string;\n}\n\nexport interface RobotsTxtGroup {\n userAgent: string;\n rules: RobotsTxtRule[];\n crawlDelay?: number;\n}\n\n// ── Helpers ───────────────────────────────────────────────────\n\n/**\n * Parses a robots.txt body into structured groups.\n * Each group has a user-agent, a list of allow/disallow rules,\n * and an optional crawl-delay value.\n */\nexport function parseRobotsTxt(body: string): RobotsTxtGroup[] {\n const groups: RobotsTxtGroup[] = [];\n let currentAgents: string[] = [];\n let currentRules: RobotsTxtRule[] = [];\n let currentCrawlDelay: number | undefined;\n\n const flushGroup = () => {\n if (currentAgents.length > 0) {\n for (const agent of currentAgents) {\n groups.push({\n userAgent: agent,\n rules: [...currentRules],\n crawlDelay: currentCrawlDelay,\n });\n }\n }\n currentAgents = [];\n currentRules = [];\n currentCrawlDelay = undefined;\n };\n\n const lines = body.split(/\\r\\n|\\r|\\n/);\n\n for (const rawLine of lines) {\n // Strip comments and trim\n const line = rawLine.replace(/#.*$/, '').trim();\n if (!line) continue;\n\n const colonIdx = line.indexOf(':');\n if (colonIdx === -1) continue;\n\n const directive = line.slice(0, colonIdx).trim().toLowerCase();\n const value = line.slice(colonIdx + 1).trim();\n\n if (directive === 'user-agent') {\n // If we already collected rules, flush the previous group\n if (currentRules.length > 0 || currentCrawlDelay !== undefined) {\n flushGroup();\n }\n currentAgents.push(value);\n } else if (directive === 'disallow') {\n currentRules.push({ type: 'disallow', path: value });\n } else if (directive === 'allow') {\n currentRules.push({ type: 'allow', path: value });\n } else if (directive === 'crawl-delay') {\n const parsed = parseFloat(value);\n if (!Number.isNaN(parsed)) {\n currentCrawlDelay = parsed;\n }\n }\n }\n\n // Flush any remaining group\n flushGroup();\n\n return groups;\n}\n\n/**\n * Returns true if the rules contain a blanket Disallow: / without a\n * counteracting Allow: /.\n */\nexport function isBlanketBlocked(rules: RobotsTxtRule[]): boolean {\n const hasDisallowRoot = rules.some(\n (r) => r.type === 'disallow' && r.path === '/',\n );\n if (!hasDisallowRoot) return false;\n\n const hasAllowRoot = rules.some(\n (r) => r.type === 'allow' && r.path === '/',\n );\n return !hasAllowRoot;\n}\n\n/**\n * Checks whether a specific bot is allowed to crawl the root path.\n *\n * Returns:\n * - `explicitly`: true if there is a group specifically for this bot\n * - `allowed`: true if the bot is not blocked (Disallow: /)\n *\n * Logic:\n * 1. Look for a group matching the bot name (case-insensitive).\n * 2. If found, check its rules for Disallow: / (with no overriding Allow: /).\n * 3. If not found, fall back to the * group.\n */\nexport function isAllowed(\n groups: RobotsTxtGroup[],\n botName: string,\n): { explicitly: boolean; allowed: boolean } {\n const botGroups = groups.filter(\n (g) => g.userAgent.toLowerCase() === botName.toLowerCase(),\n );\n\n if (botGroups.length > 0) {\n // Bot has explicit rules\n const rules = botGroups.flatMap((g) => g.rules);\n const blocked = isBlanketBlocked(rules);\n return { explicitly: true, allowed: !blocked };\n }\n\n // Fall back to wildcard\n const wildcardGroups = groups.filter((g) => g.userAgent === '*');\n if (wildcardGroups.length > 0) {\n const rules = wildcardGroups.flatMap((g) => g.rules);\n const blocked = isBlanketBlocked(rules);\n return { explicitly: false, allowed: !blocked };\n }\n\n // No robots.txt rules at all — allowed by default, but not explicitly\n return { explicitly: false, allowed: true };\n}\n\n/**\n * Check 2.3 needs to look at both \"anthropic-ai\" and \"ClaudeBot\" user-agents.\n */\nexport function isAnthropicAllowed(\n groups: RobotsTxtGroup[],\n): { explicitly: boolean; allowed: boolean } {\n const result1 = isAllowed(groups, 'anthropic-ai');\n const result2 = isAllowed(groups, 'ClaudeBot');\n\n // If both have explicit rules, pass if either alias is allowed\n if (result1.explicitly && result2.explicitly) {\n return { explicitly: true, allowed: result1.allowed || result2.allowed };\n }\n if (result1.explicitly) return result1;\n if (result2.explicitly) return result2;\n\n // Neither is explicit — fall back (both return the same wildcard result)\n return result1;\n}\n\n/**\n * Checks whether specific sensitive paths are disallowed for the wildcard\n * user-agent. Returns an object with the paths that are and aren't protected.\n */\nexport function checkSensitivePaths(\n groups: RobotsTxtGroup[],\n paths: string[],\n): { protected: string[]; unprotected: string[] } {\n const wildcardGroups = groups.filter((g) => g.userAgent === '*');\n const allRules = wildcardGroups.flatMap((g) => g.rules);\n\n const protectedPaths: string[] = [];\n const unprotectedPaths: string[] = [];\n\n for (const path of paths) {\n const pathNorm = path.replace(/\\/+$/, '');\n const isDisallowed = allRules.some((r) => {\n if (r.type !== 'disallow') return false;\n const ruleNorm = r.path.replace(/\\/+$/, '');\n return ruleNorm === pathNorm || r.path.startsWith(path) || path.startsWith(r.path);\n });\n if (isDisallowed) {\n protectedPaths.push(path);\n } else {\n unprotectedPaths.push(path);\n }\n }\n\n return { protected: protectedPaths, unprotected: unprotectedPaths };\n}\n\n// ── Crawler bot definitions ───────────────────────────────────\n\nexport interface CrawlerBot {\n id: string;\n botName: string;\n displayName: string;\n category: 'training' | 'realtime';\n /** Optional alias bot names to also check (e.g. ClaudeBot for anthropic-ai) */\n aliases?: string[];\n}\n\nexport const TRAINING_CRAWLERS: CrawlerBot[] = [\n { id: '2.1', botName: 'GPTBot', displayName: 'GPTBot', category: 'training' },\n { id: '2.2', botName: 'Google-Extended', displayName: 'Google-Extended', category: 'training' },\n { id: '2.3', botName: 'anthropic-ai', displayName: 'anthropic-ai / ClaudeBot', category: 'training', aliases: ['ClaudeBot'] },\n { id: '2.4', botName: 'PerplexityBot', displayName: 'PerplexityBot', category: 'training' },\n { id: '2.5', botName: 'Applebot-Extended', displayName: 'Applebot-Extended', category: 'training' },\n { id: '2.6', botName: 'CCBot', displayName: 'CCBot', category: 'training' },\n { id: '2.7', botName: 'Meta-ExternalAgent', displayName: 'Meta-ExternalAgent', category: 'training' },\n { id: '2.8', botName: 'Amazonbot', displayName: 'Amazonbot', category: 'training' },\n { id: '2.9', botName: 'Bytespider', displayName: 'Bytespider', category: 'training' },\n { id: '2.10', botName: 'cohere-ai', displayName: 'cohere-ai', category: 'training' },\n { id: '2.11', botName: 'YouBot', displayName: 'YouBot', category: 'training' },\n { id: '2.12', botName: 'Diffbot', displayName: 'Diffbot', category: 'training' },\n { id: '2.13', botName: 'AI2Bot', displayName: 'AI2Bot', category: 'training' },\n];\n\nexport const REALTIME_CRAWLERS: CrawlerBot[] = [\n { id: '2.14', botName: 'ChatGPT-User', displayName: 'ChatGPT-User', category: 'realtime' },\n { id: '2.15', botName: 'Claude-User', displayName: 'Claude-User', category: 'realtime' },\n { id: '2.16', botName: 'OAI-SearchBot', displayName: 'OAI-SearchBot', category: 'realtime' },\n { id: '2.17', botName: 'Meta-ExternalFetcher', displayName: 'Meta-ExternalFetcher', category: 'realtime' },\n { id: '2.18', botName: 'Bravebot', displayName: 'Bravebot', category: 'realtime' },\n { id: '2.19', botName: 'DuckAssistBot', displayName: 'DuckAssistBot', category: 'realtime' },\n { id: '2.20', botName: 'MistralAI-User', displayName: 'MistralAI-User', category: 'realtime' },\n { id: '2.21', botName: 'Claude-SearchBot', displayName: 'Claude-SearchBot', category: 'realtime' },\n];\n\nexport const ALL_CRAWLERS: CrawlerBot[] = [...TRAINING_CRAWLERS, ...REALTIME_CRAWLERS];\n","import type { AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\nimport type { CrawlerBot } from './_robots-txt-helpers';\nimport { parseRobotsTxt, isAllowed, isAnthropicAllowed } from './_robots-txt-helpers';\n\n/**\n * Base audit class for crawler bot permission checks (2.1-2.21).\n * Each bot audit extends this with the appropriate bot configuration.\n */\nexport abstract class CrawlerBotAudit extends Audit {\n protected abstract bot: CrawlerBot;\n\n audit(ctx: CheckContext): AuditResult {\n const robotsFile = ctx.rootFiles['/robots.txt'];\n const { bot } = this;\n\n // If robots.txt is missing or errored, treat as warn\n if (!robotsFile || robotsFile.status !== 200 || !robotsFile.body) {\n return this.warn(\n `robots.txt not found — ${bot.displayName} is allowed by default but not explicitly.`,\n `Explicit User-agent: ${bot.botName} with Allow: / in robots.txt`,\n 'No robots.txt found',\n {\n priority: 'medium',\n description: `Without an explicit robots.txt rule, ${bot.displayName} may still crawl your site but has no signal that it is welcome. Adding an explicit allow rule improves your visibility in AI-powered search and ensures consistent crawler behavior.`,\n code: `User-agent: ${bot.botName}\\nAllow: /`,\n },\n );\n }\n\n const groups = parseRobotsTxt(robotsFile.body);\n\n // Special handling for anthropic-ai / ClaudeBot (check 2.3)\n const result =\n bot.aliases && bot.aliases.length > 0\n ? isAnthropicAllowed(groups)\n : isAllowed(groups, bot.botName);\n\n if (result.allowed && result.explicitly) {\n return this.pass(\n `${bot.displayName} is explicitly allowed in robots.txt.`,\n `No Disallow: / for User-agent: ${bot.botName}; explicit Allow: / preferred`,\n `Explicit rules found for ${bot.botName} — access allowed`,\n );\n }\n\n if (result.allowed && !result.explicitly) {\n return this.warn(\n `${bot.displayName} is allowed by default (no specific rules), but not explicitly allowed.`,\n `No Disallow: / for User-agent: ${bot.botName}; explicit Allow: / preferred`,\n `No explicit rules for ${bot.botName} — allowed via wildcard or default`,\n {\n priority: 'medium',\n description: `${bot.displayName} is currently allowed only through the wildcard rule, which could change if you later add a blanket block. An explicit User-agent entry for ${bot.botName} ensures stable access and signals to the crawler that your site is AI-friendly.`,\n code: `User-agent: ${bot.botName}\\nAllow: /`,\n },\n );\n }\n\n // Blocked\n return this.fail(\n `${bot.displayName} is blocked by robots.txt.`,\n `No Disallow: / for User-agent: ${bot.botName}; explicit Allow: / preferred`,\n `${bot.botName} is disallowed (Disallow: /)`,\n {\n priority: 'high',\n description: `Blocking ${bot.displayName} prevents your content from appearing in AI-powered search results and answers. If you want AI assistants to reference your site, remove the Disallow rule and add an explicit Allow.`,\n code: `User-agent: ${bot.botName}\\nAllow: /`,\n },\n );\n }\n}\n","import type { AuditMeta } from \"../../types\";\nimport type { CrawlerBot } from './_robots-txt-helpers';\nimport { CrawlerBotAudit } from './_crawler-bot-audit';\n\nexport class GptbotAudit extends CrawlerBotAudit {\n static override meta: AuditMeta = {\n id: '2.1',\n category: 'crawler-permissions',\n title: 'GPTBot allowed',\n failureTitle: 'GPTBot allowed',\n description:\n 'Without an explicit robots.txt rule, GPTBot may still crawl your site but has no signal that it is welcome. Adding an explicit allow rule improves your visibility in AI-powered search and ensures consistent crawler behavior.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n \"Blocking GPTBot prevents your content from being used by OpenAI's models and appearing in ChatGPT responses. Explicitly allowing it signals that your site welcomes AI indexing for the largest AI platform by user base.\",\n fix: 'Add an explicit User-agent: GPTBot with Allow: / rule in your robots.txt file.',\n code: 'User-agent: GPTBot\\nAllow: /',\n effort: 'trivial',\n docsUrl: 'https://platform.openai.com/docs/bots/overview',\n tags: ['robots-txt', 'openai', 'crawler-permissions'],\n },\n };\n\n protected bot: CrawlerBot = {\n id: '2.1',\n botName: 'GPTBot',\n displayName: 'GPTBot',\n category: 'training',\n };\n}\n","import type { AuditMeta } from \"../../types\";\nimport type { CrawlerBot } from './_robots-txt-helpers';\nimport { CrawlerBotAudit } from './_crawler-bot-audit';\n\nexport class GoogleExtendedAudit extends CrawlerBotAudit {\n static override meta: AuditMeta = {\n id: '2.2',\n category: 'crawler-permissions',\n title: 'Google-Extended allowed',\n failureTitle: 'Google-Extended allowed',\n description:\n 'Without an explicit robots.txt rule, Google-Extended may still crawl your site but has no signal that it is welcome. Adding an explicit allow rule improves your visibility in AI-powered search and ensures consistent crawler behavior.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n \"Blocking Google-Extended prevents your content from being used in Google's AI features like Gemini and AI Overviews. Allowing it ensures your site appears in Google's AI-powered search experiences alongside traditional results.\",\n fix: 'Add an explicit User-agent: Google-Extended with Allow: / rule in your robots.txt file.',\n code: 'User-agent: Google-Extended\\nAllow: /',\n effort: 'trivial',\n docsUrl:\n 'https://developers.google.com/search/docs/crawling-indexing/overview-google-crawlers',\n tags: ['robots-txt', 'google', 'crawler-permissions'],\n },\n };\n\n protected bot: CrawlerBot = {\n id: '2.2',\n botName: 'Google-Extended',\n displayName: 'Google-Extended',\n category: 'training',\n };\n}\n","import type { AuditMeta } from \"../../types\";\nimport type { CrawlerBot } from './_robots-txt-helpers';\nimport { CrawlerBotAudit } from './_crawler-bot-audit';\n\nexport class AnthropicAudit extends CrawlerBotAudit {\n static override meta: AuditMeta = {\n id: '2.3',\n category: 'crawler-permissions',\n title: 'anthropic-ai / ClaudeBot allowed',\n failureTitle: 'anthropic-ai / ClaudeBot allowed',\n description:\n 'Without an explicit robots.txt rule, anthropic-ai / ClaudeBot may still crawl your site but has no signal that it is welcome. Adding an explicit allow rule improves your visibility in AI-powered search and ensures consistent crawler behavior.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n \"Blocking anthropic-ai / ClaudeBot prevents your content from being used by Anthropic's Claude models. Explicitly allowing it ensures your site is indexed for Claude's training data and knowledge base.\",\n fix: 'Add explicit User-agent rules for both anthropic-ai and ClaudeBot with Allow: / in your robots.txt file.',\n code: 'User-agent: anthropic-ai\\nAllow: /\\n\\nUser-agent: ClaudeBot\\nAllow: /',\n effort: 'trivial',\n tags: ['robots-txt', 'anthropic', 'crawler-permissions'],\n },\n };\n\n protected bot: CrawlerBot = {\n id: '2.3',\n botName: 'anthropic-ai',\n displayName: 'anthropic-ai / ClaudeBot',\n category: 'training',\n aliases: ['ClaudeBot'],\n };\n}\n","import type { AuditMeta } from \"../../types\";\nimport type { CrawlerBot } from './_robots-txt-helpers';\nimport { CrawlerBotAudit } from './_crawler-bot-audit';\n\nexport class PerplexitybotAudit extends CrawlerBotAudit {\n static override meta: AuditMeta = {\n id: '2.4',\n category: 'crawler-permissions',\n title: 'PerplexityBot allowed',\n failureTitle: 'PerplexityBot allowed',\n description:\n 'Without an explicit robots.txt rule, PerplexityBot may still crawl your site but has no signal that it is welcome. Adding an explicit allow rule improves your visibility in AI-powered search and ensures consistent crawler behavior.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'Blocking PerplexityBot prevents your content from appearing in Perplexity AI search results, one of the fastest-growing AI answer engines. Allowing it gives your content visibility in AI-native search.',\n fix: 'Add an explicit User-agent: PerplexityBot with Allow: / rule in your robots.txt file.',\n code: 'User-agent: PerplexityBot\\nAllow: /',\n effort: 'trivial',\n docsUrl: 'https://docs.perplexity.ai/guides/bots',\n tags: ['robots-txt', 'perplexity', 'crawler-permissions'],\n },\n };\n\n protected bot: CrawlerBot = {\n id: '2.4',\n botName: 'PerplexityBot',\n displayName: 'PerplexityBot',\n category: 'training',\n };\n}\n","import type { AuditMeta } from \"../../types\";\nimport type { CrawlerBot } from './_robots-txt-helpers';\nimport { CrawlerBotAudit } from './_crawler-bot-audit';\n\nexport class ApplebotExtendedAudit extends CrawlerBotAudit {\n static override meta: AuditMeta = {\n id: '2.5',\n category: 'crawler-permissions',\n title: 'Applebot-Extended allowed',\n failureTitle: 'Applebot-Extended allowed',\n description:\n 'Without an explicit robots.txt rule, Applebot-Extended may still crawl your site but has no signal that it is welcome. Adding an explicit allow rule improves your visibility in AI-powered search and ensures consistent crawler behavior.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n \"Blocking Applebot-Extended prevents your content from being used in Apple Intelligence features, Siri AI answers, and Safari Highlights. Allowing it ensures visibility across Apple's AI ecosystem.\",\n fix: 'Add an explicit User-agent: Applebot-Extended with Allow: / rule in your robots.txt file.',\n code: 'User-agent: Applebot-Extended\\nAllow: /',\n effort: 'trivial',\n docsUrl: 'https://support.apple.com/en-us/111042',\n tags: ['robots-txt', 'apple', 'crawler-permissions'],\n },\n };\n\n protected bot: CrawlerBot = {\n id: '2.5',\n botName: 'Applebot-Extended',\n displayName: 'Applebot-Extended',\n category: 'training',\n };\n}\n","import type { AuditMeta } from \"../../types\";\nimport type { CrawlerBot } from './_robots-txt-helpers';\nimport { CrawlerBotAudit } from './_crawler-bot-audit';\n\nexport class CcbotAudit extends CrawlerBotAudit {\n static override meta: AuditMeta = {\n id: '2.6',\n category: 'crawler-permissions',\n title: 'CCBot allowed',\n failureTitle: 'CCBot allowed',\n description:\n 'Without an explicit robots.txt rule, CCBot may still crawl your site but has no signal that it is welcome. Adding an explicit allow rule improves your visibility in AI-powered search and ensures consistent crawler behavior.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n \"Blocking CCBot prevents your content from being included in the Common Crawl dataset, which is a foundational training data source for many AI models. Allowing it broadens your content's reach across multiple AI systems.\",\n fix: 'Add an explicit User-agent: CCBot with Allow: / rule in your robots.txt file.',\n code: 'User-agent: CCBot\\nAllow: /',\n effort: 'trivial',\n docsUrl: 'https://commoncrawl.org/ccbot',\n tags: ['robots-txt', 'common-crawl', 'crawler-permissions'],\n },\n };\n\n protected bot: CrawlerBot = {\n id: '2.6',\n botName: 'CCBot',\n displayName: 'CCBot',\n category: 'training',\n };\n}\n","import type { AuditMeta } from \"../../types\";\nimport type { CrawlerBot } from './_robots-txt-helpers';\nimport { CrawlerBotAudit } from './_crawler-bot-audit';\n\nexport class MetaExternalAgentAudit extends CrawlerBotAudit {\n static override meta: AuditMeta = {\n id: '2.7',\n category: 'crawler-permissions',\n title: 'Meta-ExternalAgent allowed',\n failureTitle: 'Meta-ExternalAgent allowed',\n description:\n 'Without an explicit robots.txt rule, Meta-ExternalAgent may still crawl your site but has no signal that it is welcome. Adding an explicit allow rule improves your visibility in AI-powered search and ensures consistent crawler behavior.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n \"Blocking Meta-ExternalAgent prevents your content from being used in Meta's AI features across Facebook, Instagram, and WhatsApp. Allowing it ensures visibility in Meta's AI-powered recommendations and summaries.\",\n fix: 'Add an explicit User-agent: Meta-ExternalAgent with Allow: / rule in your robots.txt file.',\n code: 'User-agent: Meta-ExternalAgent\\nAllow: /',\n effort: 'trivial',\n tags: ['robots-txt', 'meta', 'crawler-permissions'],\n },\n };\n\n protected bot: CrawlerBot = {\n id: '2.7',\n botName: 'Meta-ExternalAgent',\n displayName: 'Meta-ExternalAgent',\n category: 'training',\n };\n}\n","import type { AuditMeta } from \"../../types\";\nimport type { CrawlerBot } from './_robots-txt-helpers';\nimport { CrawlerBotAudit } from './_crawler-bot-audit';\n\nexport class AmazonbotAudit extends CrawlerBotAudit {\n static override meta: AuditMeta = {\n id: '2.8',\n category: 'crawler-permissions',\n title: 'Amazonbot allowed',\n failureTitle: 'Amazonbot allowed',\n description:\n 'Without an explicit robots.txt rule, Amazonbot may still crawl your site but has no signal that it is welcome. Adding an explicit allow rule improves your visibility in AI-powered search and ensures consistent crawler behavior.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n \"Blocking Amazonbot prevents your content from appearing in Alexa AI answers and Amazon's AI-powered search features. Allowing it gives your content visibility in Amazon's voice and commerce AI ecosystem.\",\n fix: 'Add an explicit User-agent: Amazonbot with Allow: / rule in your robots.txt file.',\n code: 'User-agent: Amazonbot\\nAllow: /',\n effort: 'trivial',\n docsUrl: 'https://developer.amazon.com/amazonbot',\n tags: ['robots-txt', 'amazon', 'crawler-permissions'],\n },\n };\n\n protected bot: CrawlerBot = {\n id: '2.8',\n botName: 'Amazonbot',\n displayName: 'Amazonbot',\n category: 'training',\n };\n}\n","import type { AuditMeta } from \"../../types\";\nimport type { CrawlerBot } from './_robots-txt-helpers';\nimport { CrawlerBotAudit } from './_crawler-bot-audit';\n\nexport class BytespiderAudit extends CrawlerBotAudit {\n static override meta: AuditMeta = {\n id: '2.9',\n category: 'crawler-permissions',\n title: 'Bytespider allowed',\n failureTitle: 'Bytespider allowed',\n description:\n 'Without an explicit robots.txt rule, Bytespider may still crawl your site but has no signal that it is welcome. Adding an explicit allow rule improves your visibility in AI-powered search and ensures consistent crawler behavior.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n \"Blocking Bytespider prevents your content from being used by ByteDance's AI products including TikTok search and Doubao AI. Allowing it extends your content's reach to ByteDance's large user base.\",\n fix: 'Add an explicit User-agent: Bytespider with Allow: / rule in your robots.txt file.',\n code: 'User-agent: Bytespider\\nAllow: /',\n effort: 'trivial',\n tags: ['robots-txt', 'bytedance', 'crawler-permissions'],\n },\n };\n\n protected bot: CrawlerBot = {\n id: '2.9',\n botName: 'Bytespider',\n displayName: 'Bytespider',\n category: 'training',\n };\n}\n","import type { AuditMeta } from \"../../types\";\nimport type { CrawlerBot } from './_robots-txt-helpers';\nimport { CrawlerBotAudit } from './_crawler-bot-audit';\n\nexport class CohereAiAudit extends CrawlerBotAudit {\n static override meta: AuditMeta = {\n id: '2.10',\n category: 'crawler-permissions',\n title: 'cohere-ai allowed',\n failureTitle: 'cohere-ai allowed',\n description:\n 'Without an explicit robots.txt rule, cohere-ai may still crawl your site but has no signal that it is welcome. Adding an explicit allow rule improves your visibility in AI-powered search and ensures consistent crawler behavior.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n \"Blocking cohere-ai prevents your content from being used by Cohere's enterprise AI models, which power search and RAG applications for many businesses. Allowing it ensures your content is available in Cohere-powered AI search products.\",\n fix: 'Add an explicit User-agent: cohere-ai with Allow: / rule in your robots.txt file.',\n code: 'User-agent: cohere-ai\\nAllow: /',\n effort: 'trivial',\n tags: ['robots-txt', 'cohere', 'crawler-permissions'],\n },\n };\n\n protected bot: CrawlerBot = {\n id: '2.10',\n botName: 'cohere-ai',\n displayName: 'cohere-ai',\n category: 'training',\n };\n}\n","import type { AuditMeta } from \"../../types\";\nimport type { CrawlerBot } from './_robots-txt-helpers';\nimport { CrawlerBotAudit } from './_crawler-bot-audit';\n\nexport class YoubotAudit extends CrawlerBotAudit {\n static override meta: AuditMeta = {\n id: '2.11',\n category: 'crawler-permissions',\n title: 'YouBot allowed',\n failureTitle: 'YouBot allowed',\n description:\n 'Without an explicit robots.txt rule, YouBot may still crawl your site but has no signal that it is welcome. Adding an explicit allow rule improves your visibility in AI-powered search and ensures consistent crawler behavior.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'Blocking YouBot prevents your content from appearing in You.com AI search results. Allowing it gives your content visibility in this AI-native search engine that generates direct answers for users.',\n fix: 'Add an explicit User-agent: YouBot with Allow: / rule in your robots.txt file.',\n code: 'User-agent: YouBot\\nAllow: /',\n effort: 'trivial',\n tags: ['robots-txt', 'you-com', 'crawler-permissions'],\n },\n };\n\n protected bot: CrawlerBot = {\n id: '2.11',\n botName: 'YouBot',\n displayName: 'YouBot',\n category: 'training',\n };\n}\n","import type { AuditMeta } from \"../../types\";\nimport type { CrawlerBot } from './_robots-txt-helpers';\nimport { CrawlerBotAudit } from './_crawler-bot-audit';\n\nexport class DiffbotAudit extends CrawlerBotAudit {\n static override meta: AuditMeta = {\n id: '2.12',\n category: 'crawler-permissions',\n title: 'Diffbot allowed',\n failureTitle: 'Diffbot allowed',\n description:\n 'Without an explicit robots.txt rule, Diffbot may still crawl your site but has no signal that it is welcome. Adding an explicit allow rule improves your visibility in AI-powered search and ensures consistent crawler behavior.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n \"Blocking Diffbot prevents your content from being included in Diffbot's Knowledge Graph, which powers structured data extraction for many AI applications. Allowing it ensures your content is properly indexed for AI-powered entity extraction.\",\n fix: 'Add an explicit User-agent: Diffbot with Allow: / rule in your robots.txt file.',\n code: 'User-agent: Diffbot\\nAllow: /',\n effort: 'trivial',\n tags: ['robots-txt', 'diffbot', 'crawler-permissions'],\n },\n };\n\n protected bot: CrawlerBot = {\n id: '2.12',\n botName: 'Diffbot',\n displayName: 'Diffbot',\n category: 'training',\n };\n}\n","import type { AuditMeta } from \"../../types\";\nimport type { CrawlerBot } from './_robots-txt-helpers';\nimport { CrawlerBotAudit } from './_crawler-bot-audit';\n\nexport class Ai2botAudit extends CrawlerBotAudit {\n static override meta: AuditMeta = {\n id: '2.13',\n category: 'crawler-permissions',\n title: 'AI2Bot allowed',\n failureTitle: 'AI2Bot allowed',\n description:\n 'Without an explicit robots.txt rule, AI2Bot may still crawl your site but has no signal that it is welcome. Adding an explicit allow rule improves your visibility in AI-powered search and ensures consistent crawler behavior.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'Blocking AI2Bot prevents your content from being used by the Allen Institute for AI (AI2), which powers research models and semantic search tools. Allowing it contributes to open AI research and ensures broader content visibility.',\n fix: 'Add an explicit User-agent: AI2Bot with Allow: / rule in your robots.txt file.',\n code: 'User-agent: AI2Bot\\nAllow: /',\n effort: 'trivial',\n tags: ['robots-txt', 'ai2', 'crawler-permissions'],\n },\n };\n\n protected bot: CrawlerBot = {\n id: '2.13',\n botName: 'AI2Bot',\n displayName: 'AI2Bot',\n category: 'training',\n };\n}\n","import type { AuditMeta } from \"../../types\";\nimport type { CrawlerBot } from './_robots-txt-helpers';\nimport { CrawlerBotAudit } from './_crawler-bot-audit';\n\nexport class ChatgptUserAudit extends CrawlerBotAudit {\n static override meta: AuditMeta = {\n id: '2.14',\n category: 'crawler-permissions',\n title: 'ChatGPT-User allowed',\n failureTitle: 'ChatGPT-User allowed',\n description:\n 'Without an explicit robots.txt rule, ChatGPT-User may still crawl your site but has no signal that it is welcome. Adding an explicit allow rule improves your visibility in AI-powered search and ensures consistent crawler behavior.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'Blocking ChatGPT-User prevents ChatGPT from browsing your site in real-time when users ask it to visit your pages. This blocks your content from being cited in ChatGPT Browse conversations, losing a significant source of AI-driven traffic.',\n fix: 'Add an explicit User-agent: ChatGPT-User with Allow: / rule in your robots.txt file.',\n code: 'User-agent: ChatGPT-User\\nAllow: /',\n effort: 'trivial',\n docsUrl: 'https://platform.openai.com/docs/bots/overview',\n tags: ['robots-txt', 'openai', 'realtime', 'crawler-permissions'],\n },\n };\n\n protected bot: CrawlerBot = {\n id: '2.14',\n botName: 'ChatGPT-User',\n displayName: 'ChatGPT-User',\n category: 'realtime',\n };\n}\n","import type { AuditMeta } from \"../../types\";\nimport type { CrawlerBot } from './_robots-txt-helpers';\nimport { CrawlerBotAudit } from './_crawler-bot-audit';\n\nexport class ClaudeUserAudit extends CrawlerBotAudit {\n static override meta: AuditMeta = {\n id: '2.15',\n category: 'crawler-permissions',\n title: 'Claude-User allowed',\n failureTitle: 'Claude-User allowed',\n description:\n 'Without an explicit robots.txt rule, Claude-User may still crawl your site but has no signal that it is welcome. Adding an explicit allow rule improves your visibility in AI-powered search and ensures consistent crawler behavior.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'Blocking Claude-User prevents Claude from browsing your site in real-time when users ask it to visit your pages. This blocks your content from being cited in Claude conversations with web access enabled.',\n fix: 'Add an explicit User-agent: Claude-User with Allow: / rule in your robots.txt file.',\n code: 'User-agent: Claude-User\\nAllow: /',\n effort: 'trivial',\n tags: ['robots-txt', 'anthropic', 'realtime', 'crawler-permissions'],\n },\n };\n\n protected bot: CrawlerBot = {\n id: '2.15',\n botName: 'Claude-User',\n displayName: 'Claude-User',\n category: 'realtime',\n };\n}\n","import type { AuditMeta } from \"../../types\";\nimport type { CrawlerBot } from './_robots-txt-helpers';\nimport { CrawlerBotAudit } from './_crawler-bot-audit';\n\nexport class OaiSearchbotAudit extends CrawlerBotAudit {\n static override meta: AuditMeta = {\n id: '2.16',\n category: 'crawler-permissions',\n title: 'OAI-SearchBot allowed',\n failureTitle: 'OAI-SearchBot allowed',\n description:\n 'Without an explicit robots.txt rule, OAI-SearchBot may still crawl your site but has no signal that it is welcome. Adding an explicit allow rule improves your visibility in AI-powered search and ensures consistent crawler behavior.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n \"Blocking OAI-SearchBot prevents your content from appearing in OpenAI's SearchGPT and ChatGPT web search results. Allowing it ensures your site is discoverable through OpenAI's real-time search features.\",\n fix: 'Add an explicit User-agent: OAI-SearchBot with Allow: / rule in your robots.txt file.',\n code: 'User-agent: OAI-SearchBot\\nAllow: /',\n effort: 'trivial',\n docsUrl: 'https://platform.openai.com/docs/bots/overview',\n tags: ['robots-txt', 'openai', 'realtime', 'crawler-permissions'],\n },\n };\n\n protected bot: CrawlerBot = {\n id: '2.16',\n botName: 'OAI-SearchBot',\n displayName: 'OAI-SearchBot',\n category: 'realtime',\n };\n}\n","import type { AuditMeta } from \"../../types\";\nimport type { CrawlerBot } from './_robots-txt-helpers';\nimport { CrawlerBotAudit } from './_crawler-bot-audit';\n\nexport class MetaExternalFetcherAudit extends CrawlerBotAudit {\n static override meta: AuditMeta = {\n id: '2.17',\n category: 'crawler-permissions',\n title: 'Meta-ExternalFetcher allowed',\n failureTitle: 'Meta-ExternalFetcher allowed',\n description:\n 'Without an explicit robots.txt rule, Meta-ExternalFetcher may still crawl your site but has no signal that it is welcome. Adding an explicit allow rule improves your visibility in AI-powered search and ensures consistent crawler behavior.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n \"Blocking Meta-ExternalFetcher prevents Meta's AI from fetching your content in real-time for AI-powered features across Facebook, Instagram, and WhatsApp. Allowing it ensures your content can be surfaced in Meta's real-time AI experiences.\",\n fix: 'Add an explicit User-agent: Meta-ExternalFetcher with Allow: / rule in your robots.txt file.',\n code: 'User-agent: Meta-ExternalFetcher\\nAllow: /',\n effort: 'trivial',\n tags: ['robots-txt', 'meta', 'realtime', 'crawler-permissions'],\n },\n };\n\n protected bot: CrawlerBot = {\n id: '2.17',\n botName: 'Meta-ExternalFetcher',\n displayName: 'Meta-ExternalFetcher',\n category: 'realtime',\n };\n}\n","import type { AuditMeta } from \"../../types\";\nimport type { CrawlerBot } from './_robots-txt-helpers';\nimport { CrawlerBotAudit } from './_crawler-bot-audit';\n\nexport class BravebotAudit extends CrawlerBotAudit {\n static override meta: AuditMeta = {\n id: '2.18',\n category: 'crawler-permissions',\n title: 'Bravebot allowed',\n failureTitle: 'Bravebot allowed',\n description:\n 'Without an explicit robots.txt rule, Bravebot may still crawl your site but has no signal that it is welcome. Adding an explicit allow rule improves your visibility in AI-powered search and ensures consistent crawler behavior.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'Blocking Bravebot prevents your content from appearing in Brave Search AI answers and Brave Leo AI assistant responses. Allowing it gives your content visibility in the privacy-focused Brave browser ecosystem.',\n fix: 'Add an explicit User-agent: Bravebot with Allow: / rule in your robots.txt file.',\n code: 'User-agent: Bravebot\\nAllow: /',\n effort: 'trivial',\n tags: ['robots-txt', 'brave', 'realtime', 'crawler-permissions'],\n },\n };\n\n protected bot: CrawlerBot = {\n id: '2.18',\n botName: 'Bravebot',\n displayName: 'Bravebot',\n category: 'realtime',\n };\n}\n","import type { AuditMeta } from \"../../types\";\nimport type { CrawlerBot } from './_robots-txt-helpers';\nimport { CrawlerBotAudit } from './_crawler-bot-audit';\n\nexport class DuckassistbotAudit extends CrawlerBotAudit {\n static override meta: AuditMeta = {\n id: '2.19',\n category: 'crawler-permissions',\n title: 'DuckAssistBot allowed',\n failureTitle: 'DuckAssistBot allowed',\n description:\n 'Without an explicit robots.txt rule, DuckAssistBot may still crawl your site but has no signal that it is welcome. Adding an explicit allow rule improves your visibility in AI-powered search and ensures consistent crawler behavior.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n \"Blocking DuckAssistBot prevents your content from appearing in DuckDuckGo's AI-powered DuckAssist feature, which generates instant answers from crawled web pages. Allowing it ensures visibility in this privacy-first AI search experience.\",\n fix: 'Add an explicit User-agent: DuckAssistBot with Allow: / rule in your robots.txt file.',\n code: 'User-agent: DuckAssistBot\\nAllow: /',\n effort: 'trivial',\n tags: ['robots-txt', 'duckduckgo', 'realtime', 'crawler-permissions'],\n },\n };\n\n protected bot: CrawlerBot = {\n id: '2.19',\n botName: 'DuckAssistBot',\n displayName: 'DuckAssistBot',\n category: 'realtime',\n };\n}\n","import type { AuditMeta } from \"../../types\";\nimport type { CrawlerBot } from './_robots-txt-helpers';\nimport { CrawlerBotAudit } from './_crawler-bot-audit';\n\nexport class MistralaiUserAudit extends CrawlerBotAudit {\n static override meta: AuditMeta = {\n id: '2.20',\n category: 'crawler-permissions',\n title: 'MistralAI-User allowed',\n failureTitle: 'MistralAI-User allowed',\n description:\n 'Without an explicit robots.txt rule, MistralAI-User may still crawl your site but has no signal that it is welcome. Adding an explicit allow rule improves your visibility in AI-powered search and ensures consistent crawler behavior.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n \"Blocking MistralAI-User prevents Mistral AI's Le Chat from browsing your site in real-time when users ask it to visit your pages. Allowing it ensures your content can be cited in Mistral-powered AI conversations.\",\n fix: 'Add an explicit User-agent: MistralAI-User with Allow: / rule in your robots.txt file.',\n code: 'User-agent: MistralAI-User\\nAllow: /',\n effort: 'trivial',\n tags: ['robots-txt', 'mistral', 'realtime', 'crawler-permissions'],\n },\n };\n\n protected bot: CrawlerBot = {\n id: '2.20',\n botName: 'MistralAI-User',\n displayName: 'MistralAI-User',\n category: 'realtime',\n };\n}\n","import type { AuditMeta } from \"../../types\";\nimport type { CrawlerBot } from './_robots-txt-helpers';\nimport { CrawlerBotAudit } from './_crawler-bot-audit';\n\nexport class ClaudeSearchbotAudit extends CrawlerBotAudit {\n static override meta: AuditMeta = {\n id: '2.21',\n category: 'crawler-permissions',\n title: 'Claude-SearchBot allowed',\n failureTitle: 'Claude-SearchBot allowed',\n description:\n 'Without an explicit robots.txt rule, Claude-SearchBot may still crawl your site but has no signal that it is welcome. Adding an explicit allow rule improves your visibility in AI-powered search and ensures consistent crawler behavior.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n \"Blocking Claude-SearchBot prevents your content from appearing in Claude's web search results. Allowing it ensures your site is included when Claude searches the web to answer user questions.\",\n fix: 'Add an explicit User-agent: Claude-SearchBot with Allow: / rule in your robots.txt file.',\n code: 'User-agent: Claude-SearchBot\\nAllow: /',\n effort: 'trivial',\n tags: ['robots-txt', 'anthropic', 'realtime', 'crawler-permissions'],\n },\n };\n\n protected bot: CrawlerBot = {\n id: '2.21',\n botName: 'Claude-SearchBot',\n displayName: 'Claude-SearchBot',\n category: 'realtime',\n };\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\nimport { parseRobotsTxt, isBlanketBlocked } from './_robots-txt-helpers';\n\nexport class NoBlanketBlockAudit extends Audit {\n static override meta: AuditMeta = {\n id: '2.22',\n category: 'crawler-permissions',\n title: 'No blanket AI block',\n failureTitle: 'No blanket AI block',\n description:\n 'A blanket Disallow: / under User-agent: * blocks every crawler, including all AI agents. Your site becomes invisible to AI search engines, ChatGPT Browse, Perplexity, and others.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'critical',\n guidance: {\n impact:\n 'A blanket Disallow: / under User-agent: * blocks every crawler, including all AI agents. Your site becomes completely invisible to AI search engines, ChatGPT Browse, Perplexity, Claude, and all other AI-powered discovery tools.',\n fix: 'Replace the blanket Disallow: / with targeted path blocks for sensitive areas only. Allow the root path and block only private directories like /api/ and /admin/.',\n code: 'User-agent: *\\nAllow: /\\nDisallow: /api/\\nDisallow: /admin/\\nDisallow: /internal/',\n effort: 'trivial',\n docsUrl: 'https://developers.google.com/search/docs/crawling-indexing/robots/intro',\n tags: ['robots-txt', 'critical', 'crawler-permissions'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const robotsFile = ctx.rootFiles['/robots.txt'];\n\n if (!robotsFile || robotsFile.status !== 200 || !robotsFile.body) {\n return this.warn(\n 'No robots.txt found — cannot verify crawler permissions.',\n 'User-agent: * does not Disallow: / entirely',\n 'No robots.txt found',\n {\n priority: 'medium',\n description:\n 'Without a robots.txt file, there is no way to verify whether crawler permissions are correctly configured. Create a robots.txt file with explicit rules for AI crawlers.',\n code: 'User-agent: *\\nAllow: /',\n },\n );\n }\n\n const groups = parseRobotsTxt(robotsFile.body);\n const wildcardGroups = groups.filter((g) => g.userAgent === '*');\n const wildcardRules = wildcardGroups.flatMap((g) => g.rules);\n const blocked = isBlanketBlocked(wildcardRules);\n\n if (blocked) {\n return this.fail(\n 'User-agent: * has Disallow: / — this blocks all crawlers including AI agents.',\n 'User-agent: * does not Disallow: / entirely',\n 'User-agent: * contains Disallow: /',\n {\n priority: 'critical',\n description:\n 'A blanket Disallow: / under User-agent: * blocks every crawler, including all AI agents. Your site becomes invisible to AI search engines, ChatGPT Browse, Perplexity, and others. Replace it with targeted path blocks for sensitive areas only.',\n code: 'User-agent: *\\nAllow: /\\nDisallow: /api/\\nDisallow: /admin/\\nDisallow: /internal/',\n },\n );\n }\n\n return this.pass(\n 'No blanket Disallow: / found for User-agent: *.',\n 'User-agent: * does not Disallow: / entirely',\n 'Wildcard user-agent does not block all paths',\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\nimport { parseRobotsTxt, checkSensitivePaths } from './_robots-txt-helpers';\n\nconst SENSITIVE_PATHS = ['/api/', '/admin/'];\n\nexport class SensitivePathsAudit extends Audit {\n static override meta: AuditMeta = {\n id: '2.23',\n category: 'crawler-permissions',\n title: 'Sensitive paths protected',\n failureTitle: 'Sensitive paths protected',\n description:\n 'Without robots.txt, AI crawlers can access sensitive paths like /api/ and /admin/. This may expose internal endpoints, admin panels, or debug information in AI training data and search results.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'high',\n guidance: {\n impact:\n 'Without Disallow rules for sensitive paths, AI crawlers can access /api/ and /admin/ endpoints. Internal endpoints and admin interfaces could appear in AI training data or be exposed in AI-powered search results, creating security and privacy risks.',\n fix: 'Add Disallow rules in robots.txt for sensitive paths like /api/, /admin/, /internal/, and any other private directories that should not be crawled.',\n code: 'User-agent: *\\nAllow: /\\nDisallow: /api/\\nDisallow: /admin/\\nDisallow: /internal/',\n effort: 'trivial',\n tags: ['robots-txt', 'security', 'crawler-permissions'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const robotsFile = ctx.rootFiles['/robots.txt'];\n\n if (!robotsFile || robotsFile.status !== 200 || !robotsFile.body) {\n return this.warn(\n 'No robots.txt found — sensitive paths like /api/ and /admin/ are not explicitly protected.',\n '/api/, /admin/, or similar paths are disallowed in robots.txt',\n 'No robots.txt found',\n {\n priority: 'medium',\n description:\n 'Without robots.txt, AI crawlers can access sensitive paths like /api/ and /admin/. This may expose internal endpoints, admin panels, or debug information in AI training data and search results. Create a robots.txt with Disallow rules for private areas.',\n code: 'User-agent: *\\nAllow: /\\nDisallow: /api/\\nDisallow: /admin/\\nDisallow: /internal/',\n },\n );\n }\n\n const groups = parseRobotsTxt(robotsFile.body);\n const { protected: protectedPaths, unprotected } = checkSensitivePaths(groups, SENSITIVE_PATHS);\n\n if (unprotected.length === 0) {\n return this.pass(\n `Sensitive paths are protected: ${protectedPaths.join(', ')}`,\n '/api/, /admin/, or similar paths are disallowed in robots.txt',\n `Protected: ${protectedPaths.join(', ')}`,\n );\n }\n\n if (protectedPaths.length > 0) {\n return this.warn(\n `Some sensitive paths are not protected: ${unprotected.join(', ')}`,\n '/api/, /admin/, or similar paths are disallowed in robots.txt',\n `Protected: ${protectedPaths.join(', ')}; Unprotected: ${unprotected.join(', ')}`,\n {\n priority: 'medium',\n description: `Some sensitive paths are still accessible to crawlers. AI agents may index internal content from these paths, potentially exposing it in AI search results. Add Disallow rules for: ${unprotected.join(', ')}.`,\n code: unprotected.map((p) => `Disallow: ${p}`).join('\\n'),\n },\n );\n }\n\n return this.fail(\n 'No sensitive paths are protected in robots.txt. /api/ and /admin/ are accessible to all crawlers.',\n '/api/, /admin/, or similar paths are disallowed in robots.txt',\n `Unprotected: ${unprotected.join(', ')}`,\n {\n priority: 'high',\n description:\n 'None of your sensitive paths (/api/, /admin/) are protected from AI crawlers. Internal endpoints and admin interfaces could appear in AI training data or be exposed in AI-powered search results. Add Disallow rules immediately.',\n code: 'User-agent: *\\nAllow: /\\nDisallow: /api/\\nDisallow: /admin/',\n },\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\nimport { parseRobotsTxt } from './_robots-txt-helpers';\n\nexport class CrawlDelayAudit extends Audit {\n static override meta: AuditMeta = {\n id: '2.24',\n category: 'crawler-permissions',\n title: 'Crawl-delay is reasonable',\n failureTitle: 'Crawl-delay is reasonable',\n description:\n 'Excessive Crawl-delay values (over 10 seconds) dramatically slow AI indexing, meaning your latest content may take days or weeks to appear in AI search results.',\n scoreDisplayMode: 'binary',\n weight: 1.0,\n defaultPriority: 'high',\n guidance: {\n impact:\n 'Excessive Crawl-delay values (over 10 seconds) dramatically slow AI indexing, meaning your latest content may take days or weeks to appear in AI search results while competitors with lower delays get indexed faster.',\n fix: 'Reduce Crawl-delay to 5 seconds or less, or remove it entirely if your server can handle the crawl load. Most modern servers can handle AI crawler traffic without throttling.',\n code: 'User-agent: *\\nCrawl-delay: 5',\n effort: 'trivial',\n tags: ['robots-txt', 'performance', 'crawler-permissions'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const robotsFile = ctx.rootFiles['/robots.txt'];\n\n if (!robotsFile || robotsFile.status !== 200 || !robotsFile.body) {\n return this.warn(\n 'No robots.txt found — cannot verify crawler permissions.',\n 'If Crawl-delay is present, it is <= 10 seconds',\n 'No robots.txt found',\n {\n priority: 'medium',\n description:\n 'Without a robots.txt file, there is no way to verify crawl-delay settings. Create a robots.txt file to explicitly manage crawler behavior.',\n code: 'User-agent: *\\nAllow: /',\n },\n );\n }\n\n const groups = parseRobotsTxt(robotsFile.body);\n const delays = groups\n .filter((g) => g.crawlDelay !== undefined)\n .map((g) => ({ userAgent: g.userAgent, crawlDelay: g.crawlDelay! }));\n\n if (delays.length === 0) {\n return this.pass(\n 'No Crawl-delay directives found in robots.txt.',\n 'If Crawl-delay is present, it is <= 10 seconds',\n 'No Crawl-delay directives present',\n );\n }\n\n const excessive = delays.filter((d) => d.crawlDelay > 10);\n\n if (excessive.length > 0) {\n const details = excessive.map((d) => `${d.userAgent}: ${d.crawlDelay}s`).join(', ');\n return this.fail(\n `Excessive Crawl-delay values found: ${details}. Values above 10 seconds significantly slow down AI crawlers.`,\n 'If Crawl-delay is present, it is <= 10 seconds',\n `Excessive delays: ${details}`,\n {\n priority: 'high',\n description:\n 'Excessive Crawl-delay values (over 10 seconds) dramatically slow AI indexing, meaning your latest content may take days or weeks to appear in AI search results. Reduce to 5 seconds or less, or remove the directive entirely if your server can handle the load.',\n code: 'User-agent: *\\nCrawl-delay: 5',\n },\n );\n }\n\n const allDetails = delays.map((d) => `${d.userAgent}: ${d.crawlDelay}s`).join(', ');\n return this.pass(\n `Crawl-delay values are reasonable: ${allDetails}`,\n 'If Crawl-delay is present, it is <= 10 seconds',\n `Crawl-delays: ${allDetails}`,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class MetaRobotsNotBlockingAudit extends Audit {\n static override meta: AuditMeta = {\n id: '2.25',\n category: 'crawler-permissions',\n title: '<meta name=\"robots\"> not blocking',\n failureTitle: '<meta name=\"robots\"> not blocking',\n description:\n 'Pages with <meta name=\"robots\" content=\"noindex\"> are hidden from all search engines, including AI-powered ones. Ensure your important content pages do not have this tag.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'high',\n guidance: {\n impact:\n 'Pages with <meta name=\"robots\" content=\"noindex\"> are hidden from all search engines, including AI-powered ones. These pages will not appear in AI search results or be referenced by AI assistants, making their content effectively invisible.',\n fix: 'Remove the noindex directive from pages you want AI agents to discover. Replace with \"index, follow\" or remove the meta robots tag entirely.',\n code: '<meta name=\"robots\" content=\"index, follow\">',\n effort: 'trivial',\n tags: ['meta-tags', 'indexing', 'crawler-permissions'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n if (!ctx.pages || ctx.pages.length === 0) {\n return this.warn(\n 'No pages were scanned to check meta robots tags.',\n 'No noindex directive on primary content pages',\n 'No pages scanned',\n {\n priority: 'low',\n description:\n 'Pages with <meta name=\"robots\" content=\"noindex\"> are hidden from all search engines, including AI-powered ones. Ensure your important content pages do not have this tag.',\n code: '<meta name=\"robots\" content=\"index, follow\">',\n },\n );\n }\n\n const blockedPages: string[] = [];\n\n for (const page of ctx.pages) {\n const robotsContent = (page.meta['robots'] ?? '').toLowerCase();\n if (robotsContent.includes('noindex')) {\n blockedPages.push(page.url);\n }\n }\n\n if (blockedPages.length === 0) {\n return this.pass(\n 'No scanned pages have a <meta name=\"robots\"> tag with noindex.',\n 'No noindex directive on primary content pages',\n `Checked ${ctx.pages.length} page(s) — none have noindex`,\n );\n }\n\n return this.fail(\n `${blockedPages.length} page(s) have <meta name=\"robots\" content=\"noindex\">, blocking AI crawlers from indexing.`,\n 'No noindex directive on primary content pages',\n `Pages with noindex: ${blockedPages.join(', ')}`,\n {\n priority: 'high',\n description:\n 'The noindex directive on these pages prevents AI crawlers from indexing the content. This means the pages will not appear in AI search results or be referenced by AI assistants. Remove the noindex tag from pages you want AI agents to discover.',\n code: '<!-- Replace noindex with: -->\\n<meta name=\"robots\" content=\"index, follow\">',\n },\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nconst BOT_DETECTION_PATTERNS: Array<{\n name: string;\n pattern: string;\n}> = [\n { name: 'Cloudflare Turnstile', pattern: 'challenges.cloudflare.com' },\n { name: 'DataDome', pattern: 'datadome.co' },\n { name: 'hCaptcha', pattern: 'hcaptcha.com' },\n { name: 'reCAPTCHA', pattern: 'recaptcha' },\n];\n\nexport class NoBotDetectionAudit extends Audit {\n static override meta: AuditMeta = {\n id: '2.26',\n category: 'crawler-permissions',\n title: 'No aggressive bot-detection blocking agents',\n failureTitle: 'No aggressive bot-detection blocking agents',\n description:\n 'Bot-detection services like Cloudflare Turnstile, DataDome, and reCAPTCHA can block legitimate AI agents from accessing your content. Configure your service to allowlist known AI user-agents.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'high',\n guidance: {\n impact:\n 'Bot-detection services like Cloudflare Turnstile, DataDome, and reCAPTCHA can block legitimate AI agents from accessing your content. When agents are challenged, they cannot complete page fetches, making your content inaccessible to AI-powered search and assistants.',\n fix: 'Configure your bot-detection service to allowlist known AI agent user-agents (GPTBot, ChatGPT-User, Claude-User, PerplexityBot) so they bypass challenges while still protecting against malicious bots.',\n code: '// Allowlist these AI agent user-agents in your WAF/CDN config:\\n// GPTBot, ChatGPT-User, OAI-SearchBot (OpenAI)\\n// Claude-User, Claude-SearchBot, anthropic-ai (Anthropic)\\n// PerplexityBot, Google-Extended, Bravebot, DuckAssistBot',\n effort: 'moderate',\n tags: ['security', 'bot-detection', 'crawler-permissions'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n // If active WAF protection or aggressive connection dropping was detected\n if (ctx.wafProtection?.isBlocked) {\n return this.fail(\n `Bot-defense firewall detected blocking AI crawler connections: ${ctx.wafProtection.name} (${ctx.wafProtection.reason}).`,\n 'No JavaScript-based bot challenges that would block legitimate AI agents',\n `Blocked by ${ctx.wafProtection.name}`,\n {\n priority: 'critical',\n description:\n 'A Web Application Firewall (WAF) or bot defense system is actively dropping, resetting, or challenging crawler HTTP connections. Legitimate AI search crawlers (GPTBot, Claude, Perplexity) cannot access or index your store content unless allowlisted.',\n code: '// Example: Allowlist AI crawler user-agents in your WAF settings\\n// Akamai / Cloudflare / DataDome WAF Custom Rules:\\n// Allow User-Agent matching \"GPTBot\" OR \"ChatGPT-User\" OR \"Claude-User\" OR \"PerplexityBot\"',\n },\n );\n }\n\n if (!ctx.pages || ctx.pages.length === 0) {\n return this.warn(\n 'No pages were scanned to check for bot-detection scripts.',\n 'No JavaScript-based bot challenges that would block legitimate AI agents',\n 'No pages scanned',\n {\n priority: 'low',\n description:\n 'Aggressive bot-detection scripts can block legitimate AI agents like ChatGPT Browse, Google Mariner, and Claude from accessing your pages. Ensure your security settings allowlist known AI user-agents.',\n code: '// Example: allowlist AI agents in your WAF/CDN config\\n// Cloudflare: Security > WAF > Custom Rules\\n// Allow User-Agent contains \"GPTBot\" OR \"ChatGPT-User\" OR \"Claude-User\"',\n },\n );\n }\n\n const detectedServices: Map<string, string[]> = new Map();\n\n for (const page of ctx.pages) {\n const html = page.fetchResult.body.toLowerCase();\n\n for (const { name: serviceName, pattern } of BOT_DETECTION_PATTERNS) {\n if (html.includes(pattern.toLowerCase())) {\n if (!detectedServices.has(serviceName)) {\n detectedServices.set(serviceName, []);\n }\n detectedServices.get(serviceName)!.push(page.url);\n }\n }\n }\n\n if (detectedServices.size === 0) {\n return this.pass(\n 'No aggressive bot-detection scripts found on scanned pages.',\n 'No JavaScript-based bot challenges that would block legitimate AI agents',\n `Checked ${ctx.pages.length} page(s) — no bot-detection scripts found`,\n );\n }\n\n const serviceNames = Array.from(detectedServices.keys());\n const details = serviceNames\n .map((s) => `${s} (on ${detectedServices.get(s)!.length} page(s))`)\n .join('; ');\n\n return this.warn(\n `Bot-detection scripts detected: ${details}. These may block legitimate AI agents like ChatGPT Agent, GoogleAgent-Mariner, and NovaAct.`,\n 'No JavaScript-based bot challenges that would block legitimate AI agents',\n `Detected: ${serviceNames.join(', ')}`,\n {\n priority: 'high',\n description:\n 'Bot-detection services like Cloudflare Turnstile, DataDome, and reCAPTCHA can block legitimate AI agents from accessing your content. Configure your service to allowlist known AI user-agents so they are not challenged, while still protecting against malicious bots.',\n code: '// Allowlist these AI agent user-agents in your bot-detection config:\\n// GPTBot, ChatGPT-User, OAI-SearchBot (OpenAI)\\n// Claude-User, Claude-SearchBot, anthropic-ai (Anthropic)\\n// PerplexityBot (Perplexity)\\n// Google-Extended (Google AI)\\n// Bravebot, DuckAssistBot\\n//\\n// Example Cloudflare WAF rule:\\n// IF User-Agent contains \"ChatGPT-User\" OR \"Claude-User\"\\n// THEN Skip all managed challenges',\n },\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class JsonLdPresentAudit extends Audit {\n static override meta: AuditMeta = {\n id: '3.1',\n category: 'structured-data',\n title: 'JSON-LD present',\n failureTitle: 'JSON-LD present',\n description:\n 'AI agents rely on JSON-LD structured data to understand what your site offers, who runs it, and how to interact with it. Without any JSON-LD, agents like ChatGPT and Perplexity treat your site as unstructured text with no machine-readable identity. Add Organization and WebSite schemas to your homepage <head> as a starting point.',\n scoreDisplayMode: 'binary',\n weight: 1.0,\n defaultPriority: 'critical',\n guidance: {\n impact:\n 'Without any JSON-LD structured data, AI agents like ChatGPT and Perplexity treat your site as unstructured text with no machine-readable identity. Your brand, products, and services become invisible to AI-powered discovery, search, and recommendation systems.',\n fix: 'Add at least one JSON-LD script block in your homepage <head>. Start with Organization and WebSite schemas to establish your site identity for AI agents.',\n code: `<script type=\"application/ld+json\">\n{\n \"@context\": \"https://schema.org\",\n \"@type\": \"Organization\",\n \"name\": \"Your Company\",\n \"url\": \"https://yoursite.com\",\n \"logo\": \"https://yoursite.com/logo.png\"\n}\n</script>`,\n effort: 'easy',\n docsUrl:\n 'https://developers.google.com/search/docs/appearance/structured-data/intro-structured-data',\n tags: ['json-ld', 'schema', 'foundation'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const allBlocks = ctx.pages.flatMap((p) => p.jsonLd);\n const found = allBlocks.length > 0;\n\n if (found) {\n return this.pass(\n `Found ${allBlocks.length} JSON-LD block(s) across ${ctx.pages.length} page(s).`,\n 'At least one valid JSON-LD block across all pages.',\n `${allBlocks.length} JSON-LD block(s)`,\n );\n }\n\n return this.fail(\n 'No JSON-LD structured data found on any page.',\n 'At least one valid JSON-LD block across all pages.',\n 'None',\n {\n priority: 'critical',\n description:\n 'AI agents rely on JSON-LD structured data to understand what your site offers, who runs it, and how to interact with it. Without any JSON-LD, agents like ChatGPT and Perplexity treat your site as unstructured text with no machine-readable identity. Add Organization and WebSite schemas to your homepage <head> as a starting point.',\n code: `<script type=\"application/ld+json\">\n{\n \"@context\": \"https://schema.org\",\n \"@type\": \"Organization\",\n \"name\": \"Your Company\",\n \"url\": \"https://yoursite.com\",\n \"logo\": \"https://yoursite.com/logo.png\"\n}\n</script>`,\n docsUrl:\n 'https://developers.google.com/search/docs/appearance/structured-data/intro-structured-data',\n },\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\nimport { flattenJsonLd } from '../../parser';\n\nexport class SchemaValidationAudit extends Audit {\n static override meta: AuditMeta = {\n id: '3.2',\n category: 'structured-data',\n title: 'Schema validation',\n failureTitle: 'Schema validation',\n description:\n 'AI agents parse @context and @type to identify entity types in your structured data. Blocks missing these properties are silently ignored by every schema consumer, including Google, ChatGPT plugins, and RAG pipelines. Add \"@context\": \"https://schema.org\" and a valid @type to each block.',\n scoreDisplayMode: 'binary',\n weight: 1.0,\n defaultPriority: 'critical',\n guidance: {\n impact:\n 'JSON-LD blocks missing @context or @type are silently ignored by every schema consumer, including Google, ChatGPT plugins, and RAG pipelines. Even if you have structured data on the page, invalid blocks provide zero value to AI agents.',\n fix: 'Ensure every JSON-LD block includes \"@context\": \"https://schema.org\" and a valid @type property. If using @graph, each item inside must also have @type.',\n code: `<script type=\"application/ld+json\">\n{\n \"@context\": \"https://schema.org\",\n \"@type\": \"WebPage\",\n \"name\": \"Page Title\",\n \"description\": \"Page description\"\n}\n</script>`,\n effort: 'trivial',\n docsUrl: 'https://json-ld.org/spec/latest/json-ld/',\n tags: ['json-ld', 'schema', 'validation', 'foundation'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n // Keep each block tied to the page it came from, so a failure can name\n // *which* blocks (by @type) and *where* they are — not just a count.\n // `@graph` containers are JSON-LD document wrappers, not schema entities:\n // they legitimately carry only @context + @graph and no @type, so they must\n // not be validated as blocks (their children are flattened out separately).\n const flat: Array<{ obj: Record<string, unknown>; pageUrl: string }> = [];\n for (const p of ctx.pages) {\n for (const b of flattenJsonLd(p.structuredData ?? p.jsonLd)) {\n const obj = b as Record<string, unknown>;\n if ('@graph' in obj) continue;\n // Pure node references (e.g. `{ \"@id\": \"...\" }`) are references, not entity blocks\n const keys = Object.keys(obj);\n if (!obj['@type'] && keys.every((k) => k === '@id' || k === '@context')) {\n continue;\n }\n flat.push({ obj, pageUrl: p.url });\n }\n }\n\n if (flat.length === 0) {\n return this.fail(\n 'No JSON-LD blocks to validate.',\n 'All JSON-LD blocks have @context and @type.',\n 'No JSON-LD blocks found.',\n {\n priority: 'critical',\n description:\n 'AI agents parse @context and @type to determine the schema vocabulary and entity type. Without these properties, the JSON-LD block is meaningless to any machine reader. Ensure every JSON-LD block includes \"@context\": \"https://schema.org\" and a valid @type.',\n code: `<script type=\"application/ld+json\">\n{\n \"@context\": \"https://schema.org\",\n \"@type\": \"WebPage\",\n \"name\": \"Page Title\"\n}\n</script>`,\n },\n );\n }\n\n const invalid = flat.filter(({ obj }) => !obj['@context'] || !obj['@type']);\n\n if (invalid.length === 0) {\n return this.pass(\n `All ${flat.length} schema block(s) have valid @context and @type.`,\n 'All JSON-LD blocks have @context and @type.',\n `${flat.length}/${flat.length} valid`,\n );\n }\n\n // Name the offenders — \"<@type> on <path>\" — deduped and capped so the\n // one-line reason stays scannable in the report.\n const offenders = [\n ...new Set(invalid.map(({ obj, pageUrl }) => `${schemaType(obj['@type'])} on ${pathOf(pageUrl)}`)),\n ];\n const shown = offenders.slice(0, 4).join(', ');\n const more = offenders.length > 4 ? ` +${offenders.length - 4} more` : '';\n\n return this.fail(\n `${invalid.length} of ${flat.length} schema block(s) missing @context or @type — ${shown}${more}.`,\n 'All JSON-LD blocks have @context and @type.',\n `${flat.length - invalid.length}/${flat.length} valid`,\n {\n priority: 'high',\n description:\n 'AI agents parse @context and @type to identify entity types in your structured data. Blocks missing these properties are silently ignored by every schema consumer, including Google, ChatGPT plugins, and RAG pipelines. Add \"@context\": \"https://schema.org\" and a valid @type to each block.',\n code: `\"@context\": \"https://schema.org\",\n\"@type\": \"WebPage\"`,\n },\n );\n }\n}\n\n/** Short label for a JSON-LD `@type` (first of an array; last path segment). */\nfunction schemaType(type: unknown): string {\n const t = Array.isArray(type) ? type.find((v) => typeof v === 'string' && v) : type;\n if (typeof t === 'string' && t.trim()) return t.split(/[/#]/).pop() || t;\n return '(untyped)';\n}\n\n/** Path portion of a page URL, for compact \"on /path\" labels. */\nfunction pathOf(url: string): string {\n try {\n return new URL(url).pathname || '/';\n } catch {\n return url;\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\nimport { flattenJsonLd } from '../../parser';\n\nconst ORG_TYPES = [\n 'Organization',\n 'Corporation',\n 'LocalBusiness',\n 'Store',\n 'OnlineStore',\n 'OnlineBusiness',\n 'EducationalOrganization',\n 'GovernmentOrganization',\n 'NGO',\n 'NewsMediaOrganization',\n 'MedicalOrganization',\n 'SportsOrganization',\n];\n\nfunction matchesOrgType(schema: Record<string, unknown>): boolean {\n const t = schema['@type'];\n if (typeof t === 'string') return ORG_TYPES.includes(t) || t.endsWith('Organization') || t.endsWith('Store') || t.endsWith('Business');\n if (Array.isArray(t)) return t.some((item) => typeof item === 'string' && (ORG_TYPES.includes(item) || item.endsWith('Organization') || item.endsWith('Store') || item.endsWith('Business')));\n return false;\n}\n\nfunction allSchemas(ctx: CheckContext): object[] {\n return ctx.pages.flatMap((p) => flattenJsonLd(p.structuredData ?? p.jsonLd));\n}\n\nfunction hasProps(obj: Record<string, unknown>, keys: string[]): string[] {\n return keys.filter((k) => !obj[k]);\n}\n\nexport class OrganizationSchemaAudit extends Audit {\n static override meta: AuditMeta = {\n id: '3.3',\n category: 'structured-data',\n title: 'Organization schema',\n failureTitle: 'Organization schema',\n description:\n 'AI agents use Organization schema to identify your brand, logo, and contact info. Without it, agents cannot confidently attribute content to your organization or display your branding in AI-generated answers. Add this JSON-LD to your homepage <head>.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n applicablePageTypes: ['homepage'],\n defaultPriority: 'high',\n guidance: {\n impact:\n 'Without Organization schema, AI agents cannot confidently attribute content to your brand or display your logo in AI-generated answers. Your organization becomes anonymous in AI recommendations, losing brand visibility and trust signals.',\n fix: 'Add Organization JSON-LD to your homepage <head>. Include name, url, and logo at minimum. Optionally add sameAs links to social profiles and contactPoint for customer service.',\n code: `{\n \"@context\": \"https://schema.org\",\n \"@type\": \"Organization\",\n \"name\": \"Your Company\",\n \"url\": \"https://yoursite.com\",\n \"logo\": \"https://yoursite.com/logo.png\",\n \"sameAs\": [\n \"https://twitter.com/yourcompany\",\n \"https://linkedin.com/company/yourcompany\"\n ]\n}`,\n effort: 'trivial',\n docsUrl: 'https://schema.org/Organization',\n tags: ['json-ld', 'schema', 'organization', 'brand'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const schemas = allSchemas(ctx);\n const orgSchemas = schemas.filter((s) =>\n matchesOrgType(s as Record<string, unknown>),\n );\n\n if (orgSchemas.length === 0) {\n return this.fail(\n 'No Organization schema found.',\n 'Organization schema with name, url, and logo.',\n 'None',\n {\n priority: 'high',\n description:\n 'AI agents use Organization schema to identify your brand, logo, and contact info. Without it, agents cannot confidently attribute content to your organization or display your branding in AI-generated answers. Add this JSON-LD to your homepage <head>.',\n code: `<script type=\"application/ld+json\">\n{\n \"@context\": \"https://schema.org\",\n \"@type\": \"Organization\",\n \"name\": \"Your Company\",\n \"url\": \"https://yoursite.com\",\n \"logo\": \"https://yoursite.com/logo.png\"\n}\n</script>`,\n },\n );\n }\n\n const requiredProps = ['name', 'url', 'logo'];\n const org = orgSchemas[0] as Record<string, unknown>;\n const missing = hasProps(org, requiredProps);\n const valid = missing.length === 0;\n\n if (valid) {\n return this.pass(\n 'Organization schema found with name, url, and logo.',\n 'Organization schema with name, url, and logo.',\n 'Complete Organization schema',\n );\n }\n\n return this.warn(\n `Organization schema found but missing: ${missing.join(', ')}.`,\n 'Organization schema with name, url, and logo.',\n `Organization schema missing ${missing.join(', ')}`,\n {\n priority: 'high',\n description: `AI agents use Organization schema properties to identify your brand, display your logo, and link to your site. Missing properties (${missing.join(', ')}) reduce your organization's visibility in AI-generated answers. Add them to your existing Organization schema.`,\n code: `{\n \"@context\": \"https://schema.org\",\n \"@type\": \"Organization\",\n \"name\": \"Your Company\",\n \"url\": \"https://yoursite.com\",\n \"logo\": \"https://yoursite.com/logo.png\"\n}`,\n },\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\nimport { flattenJsonLd } from '../../parser';\n\nfunction matchesType(schema: Record<string, unknown>, type: string): boolean {\n const t = schema['@type'];\n if (typeof t === 'string') return t === type;\n if (Array.isArray(t)) return t.includes(type);\n return false;\n}\n\nfunction allSchemas(ctx: CheckContext): object[] {\n return ctx.pages.flatMap((p) => flattenJsonLd(p.structuredData ?? p.jsonLd));\n}\n\nexport class WebSiteSearchActionAudit extends Audit {\n static override meta: AuditMeta = {\n id: '3.4',\n category: 'structured-data',\n title: 'WebSite schema with SearchAction',\n failureTitle: 'WebSite schema with SearchAction',\n description:\n 'SearchAction tells AI agents how to search your site programmatically. When a user asks ChatGPT to \"find X on yoursite.com\", the agent uses this schema to construct a search URL. Without it, agents have no machine-readable way to query your content.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n applicablePageTypes: ['homepage'],\n defaultPriority: 'high',\n guidance: {\n impact:\n 'Without WebSite schema with SearchAction, AI agents have no machine-readable way to search your site. When a user asks ChatGPT to \"find X on yoursite.com\", the agent cannot construct a search URL and will either skip your site or guess incorrectly.',\n fix: 'Add WebSite JSON-LD to your homepage with a potentialAction of type SearchAction. The target must be a URL template with a {search_term_string} placeholder, and query-input must declare the parameter name.',\n code: `{\n \"@context\": \"https://schema.org\",\n \"@type\": \"WebSite\",\n \"url\": \"https://yoursite.com\",\n \"potentialAction\": {\n \"@type\": \"SearchAction\",\n \"target\": \"https://yoursite.com/search?q={search_term_string}\",\n \"query-input\": \"required name=search_term_string\"\n }\n}`,\n effort: 'trivial',\n docsUrl: 'https://schema.org/SearchAction',\n tags: ['json-ld', 'schema', 'search', 'website', 'sitelinks'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const schemas = allSchemas(ctx);\n const webSites = schemas.filter((s) => matchesType(s as Record<string, unknown>, 'WebSite'));\n\n if (webSites.length === 0) {\n return this.fail(\n 'No WebSite schema found.',\n 'WebSite schema with potentialAction SearchAction and target URL template.',\n 'None',\n {\n priority: 'high',\n description:\n 'SearchAction tells AI agents how to search your site programmatically. When a user asks ChatGPT to \"find X on yoursite.com\", the agent uses this schema to construct a search URL. Without it, agents have no machine-readable way to query your content.',\n code: `<script type=\"application/ld+json\">\n{\n \"@context\": \"https://schema.org\",\n \"@type\": \"WebSite\",\n \"url\": \"https://yoursite.com\",\n \"potentialAction\": {\n \"@type\": \"SearchAction\",\n \"target\": \"https://yoursite.com/search?q={search_term_string}\",\n \"query-input\": \"required name=search_term_string\"\n }\n}\n</script>`,\n },\n );\n }\n\n const ws = webSites[0] as Record<string, unknown>;\n const action = ws['potentialAction'] as Record<string, unknown> | undefined;\n const hasSearchAction =\n action &&\n matchesType(action, 'SearchAction') &&\n typeof action['target'] === 'string' &&\n action['target'].includes('{');\n\n if (hasSearchAction) {\n return this.pass(\n 'WebSite schema with SearchAction and URL template found.',\n 'WebSite schema with potentialAction SearchAction and target URL template.',\n 'Complete WebSite SearchAction',\n );\n }\n\n return this.warn(\n 'WebSite schema found but missing proper SearchAction with target URL template.',\n 'WebSite schema with potentialAction SearchAction and target URL template.',\n 'WebSite schema without proper SearchAction',\n {\n priority: 'medium',\n description:\n 'SearchAction tells AI agents how to search your site programmatically. When a user asks an AI agent to \"find X on yoursite.com\", the agent uses this schema to construct a search URL and return results. Add a potentialAction with a target URL template.',\n code: `\"potentialAction\": {\n \"@type\": \"SearchAction\",\n \"target\": \"https://yoursite.com/search?q={search_term_string}\",\n \"query-input\": \"required name=search_term_string\"\n}`,\n },\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\nimport { flattenJsonLd } from '../../parser';\n\nfunction matchesType(schema: Record<string, unknown>, type: string): boolean {\n const t = schema['@type'];\n if (typeof t === 'string') return t === type;\n if (Array.isArray(t)) return t.includes(type);\n return false;\n}\n\nfunction urlDepth(url: string): number {\n try {\n const pathname = new URL(url).pathname;\n return pathname.split('/').filter(Boolean).length;\n } catch {\n return 0;\n }\n}\n\nexport class BreadcrumbSchemaAudit extends Audit {\n static override meta: AuditMeta = {\n id: '3.5',\n category: 'structured-data',\n title: 'BreadcrumbList schema',\n failureTitle: 'BreadcrumbList schema',\n description:\n 'AI agents use BreadcrumbList to understand your site hierarchy and navigate between parent/child pages. Without breadcrumbs, agents cannot infer where a page sits in your content tree, making it harder to provide contextual answers that reference related pages.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n applicablePageTypes: ['category', 'product', 'content'],\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'Without BreadcrumbList schema, AI agents cannot infer where a page sits in your site hierarchy. This prevents agents from navigating between parent and child pages and from providing contextual answers that reference related pages in your content tree.',\n fix: 'Add BreadcrumbList JSON-LD to every page with URL depth greater than 1. Each ListItem should include position, name, and item (the URL).',\n code: `{\n \"@context\": \"https://schema.org\",\n \"@type\": \"BreadcrumbList\",\n \"itemListElement\": [\n { \"@type\": \"ListItem\", \"position\": 1, \"name\": \"Home\", \"item\": \"https://yoursite.com/\" },\n { \"@type\": \"ListItem\", \"position\": 2, \"name\": \"Category\", \"item\": \"https://yoursite.com/category/\" },\n { \"@type\": \"ListItem\", \"position\": 3, \"name\": \"Current Page\", \"item\": \"https://yoursite.com/category/page/\" }\n ]\n}`,\n effort: 'easy',\n docsUrl: 'https://schema.org/BreadcrumbList',\n tags: ['json-ld', 'schema', 'navigation', 'site-structure'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const deepPages = ctx.pages.filter((p) => urlDepth(p.url) > 1);\n\n if (deepPages.length === 0) {\n return this.warn(\n 'No pages with URL depth > 1 found to evaluate breadcrumbs.',\n 'BreadcrumbList schema on pages with URL depth > 1.',\n 'No deep pages detected.',\n {\n priority: 'low',\n description:\n 'AI agents use BreadcrumbList to understand site hierarchy and navigate between related pages. If your site has pages nested beyond the root level, add BreadcrumbList JSON-LD to help agents map your content structure.',\n code: `{\n \"@context\": \"https://schema.org\",\n \"@type\": \"BreadcrumbList\",\n \"itemListElement\": [\n { \"@type\": \"ListItem\", \"position\": 1, \"name\": \"Home\", \"item\": \"https://yoursite.com/\" },\n { \"@type\": \"ListItem\", \"position\": 2, \"name\": \"Category\", \"item\": \"https://yoursite.com/category/\" }\n ]\n}`,\n },\n );\n }\n\n const pagesWithBreadcrumb = deepPages.filter((p) => {\n const schemas = flattenJsonLd(p.structuredData ?? p.jsonLd);\n return schemas.some((s) => matchesType(s as Record<string, unknown>, 'BreadcrumbList'));\n });\n\n const allHave = pagesWithBreadcrumb.length === deepPages.length;\n const someHave = pagesWithBreadcrumb.length > 0;\n\n if (allHave) {\n return this.pass(\n `BreadcrumbList schema present on all ${deepPages.length} deep page(s).`,\n 'BreadcrumbList schema on pages with URL depth > 1.',\n `${pagesWithBreadcrumb.length}/${deepPages.length} deep pages have BreadcrumbList`,\n );\n }\n\n if (someHave) {\n return this.warn(\n `BreadcrumbList schema found on ${pagesWithBreadcrumb.length} of ${deepPages.length} deep page(s).`,\n 'BreadcrumbList schema on pages with URL depth > 1.',\n `${pagesWithBreadcrumb.length}/${deepPages.length} deep pages have BreadcrumbList`,\n {\n priority: 'medium',\n description:\n 'AI agents use BreadcrumbList to understand your site hierarchy and navigate between parent/child pages. Without breadcrumbs, agents cannot infer where a page sits in your content tree, making it harder to provide contextual answers that reference related pages.',\n code: `{\n \"@context\": \"https://schema.org\",\n \"@type\": \"BreadcrumbList\",\n \"itemListElement\": [\n { \"@type\": \"ListItem\", \"position\": 1, \"name\": \"Home\", \"item\": \"https://yoursite.com/\" },\n { \"@type\": \"ListItem\", \"position\": 2, \"name\": \"Category\", \"item\": \"https://yoursite.com/category/\" }\n ]\n}`,\n },\n );\n }\n\n return this.fail(\n `No BreadcrumbList schema found on ${deepPages.length} deep page(s).`,\n 'BreadcrumbList schema on pages with URL depth > 1.',\n `${pagesWithBreadcrumb.length}/${deepPages.length} deep pages have BreadcrumbList`,\n {\n priority: 'medium',\n description:\n 'AI agents use BreadcrumbList to understand your site hierarchy and navigate between parent/child pages. Without breadcrumbs, agents cannot infer where a page sits in your content tree, making it harder to provide contextual answers that reference related pages.',\n code: `{\n \"@context\": \"https://schema.org\",\n \"@type\": \"BreadcrumbList\",\n \"itemListElement\": [\n { \"@type\": \"ListItem\", \"position\": 1, \"name\": \"Home\", \"item\": \"https://yoursite.com/\" },\n { \"@type\": \"ListItem\", \"position\": 2, \"name\": \"Category\", \"item\": \"https://yoursite.com/category/\" }\n ]\n}`,\n },\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext, PageContext } from '../../check-context';\nimport { flattenJsonLd } from '../../parser';\n\nconst ARTICLE_TYPES = ['Article', 'NewsArticle', 'BlogPosting'];\n\nfunction matchesAnyType(schema: Record<string, unknown>, types: string[]): boolean {\n return types.some((t) => {\n const st = schema['@type'];\n if (typeof st === 'string') return st === t;\n if (Array.isArray(st)) return st.includes(t);\n return false;\n });\n}\n\n/**\n * A page is article content if it was classified as a content page OR it\n * directly carries Article/BlogPosting/NewsArticle schema. The previous\n * `/blog/` (singular) URL gate missed Shopify's `/blogs/news` and `/pages/blog`\n * routes, producing false \"no blog content\" verdicts on real stores.\n */\nfunction isArticlePage(page: PageContext): boolean {\n if (page.pageType === 'content') return true;\n const schemas = flattenJsonLd(page.structuredData ?? page.jsonLd);\n return schemas.some((s) => matchesAnyType(s as Record<string, unknown>, ARTICLE_TYPES));\n}\n\nfunction hasProps(obj: Record<string, unknown>, keys: string[]): string[] {\n return keys.filter((k) => !obj[k]);\n}\n\nexport class ArticleSchemaAudit extends Audit {\n static override meta: AuditMeta = {\n id: '3.6',\n category: 'structured-data',\n title: 'Article schema',\n failureTitle: 'Article schema',\n description:\n 'AI agents extract Article schema to identify content freshness (datePublished/dateModified), authorship, and topic (headline). Without it, your blog content is treated as generic text with no provenance, reducing its chances of being cited in AI-generated answers.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n applicablePageTypes: ['content'],\n defaultPriority: 'high',\n guidance: {\n impact:\n 'Without Article schema, AI answer engines treat your blog content as generic text with no provenance. You lose content freshness signals (datePublished/dateModified), authorship attribution, and headline extraction -- all of which reduce your chances of being cited in AI-generated answers.',\n fix: 'Add Article or BlogPosting JSON-LD to every blog page. Include headline, datePublished, dateModified, and author with a nested Person type.',\n code: `{\n \"@context\": \"https://schema.org\",\n \"@type\": \"Article\",\n \"headline\": \"Your Article Title\",\n \"datePublished\": \"2025-01-15\",\n \"dateModified\": \"2025-02-01\",\n \"author\": {\n \"@type\": \"Person\",\n \"name\": \"Author Name\"\n }\n}`,\n effort: 'easy',\n docsUrl: 'https://schema.org/Article',\n tags: ['json-ld', 'schema', 'content', 'article', 'blog'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const blogPages = ctx.pages.filter((p) => isArticlePage(p));\n\n if (blogPages.length === 0) {\n return this.notApplicable(\n 'No blog/content pages scanned to evaluate Article schema.',\n 'Article schema with headline, datePublished, dateModified, author on blog pages.',\n 'No content pages or Article schema detected.',\n );\n }\n\n const requiredProps = ['headline', 'datePublished', 'dateModified', 'author'];\n let completeCount = 0;\n let partialCount = 0;\n\n for (const page of blogPages) {\n const schemas = flattenJsonLd(page.structuredData ?? page.jsonLd);\n const articles = schemas.filter((s) =>\n matchesAnyType(s as Record<string, unknown>, ARTICLE_TYPES),\n );\n\n if (articles.length > 0) {\n const art = articles[0] as Record<string, unknown>;\n const missing = hasProps(art, requiredProps);\n if (missing.length === 0) {\n completeCount++;\n } else {\n partialCount++;\n }\n }\n }\n\n const allComplete = completeCount === blogPages.length;\n const someFound = completeCount + partialCount > 0;\n\n if (allComplete) {\n return this.pass(\n `Article schema with all required properties found on all ${blogPages.length} blog page(s).`,\n 'Article schema with headline, datePublished, dateModified, author on blog pages.',\n `${completeCount} complete, ${partialCount} partial, out of ${blogPages.length} blog page(s)`,\n );\n }\n\n if (someFound) {\n return this.warn(\n `Article schema found on ${completeCount + partialCount} of ${blogPages.length} blog page(s), ${completeCount} complete.`,\n 'Article schema with headline, datePublished, dateModified, author on blog pages.',\n `${completeCount} complete, ${partialCount} partial, out of ${blogPages.length} blog page(s)`,\n {\n priority: 'high',\n description:\n 'AI agents extract Article schema to identify content freshness (datePublished/dateModified), authorship, and topic (headline). Without it, your blog content is treated as generic text with no provenance, reducing its chances of being cited in AI-generated answers.',\n code: `{\n \"@context\": \"https://schema.org\",\n \"@type\": \"Article\",\n \"headline\": \"Article Title\",\n \"datePublished\": \"2025-01-01\",\n \"dateModified\": \"2025-01-02\",\n \"author\": { \"@type\": \"Person\", \"name\": \"Author Name\" }\n}`,\n },\n );\n }\n\n return this.fail(\n `No Article schema found on ${blogPages.length} blog page(s).`,\n 'Article schema with headline, datePublished, dateModified, author on blog pages.',\n `${completeCount} complete, ${partialCount} partial, out of ${blogPages.length} blog page(s)`,\n {\n priority: 'high',\n description:\n 'AI agents extract Article schema to identify content freshness (datePublished/dateModified), authorship, and topic (headline). Without it, your blog content is treated as generic text with no provenance, reducing its chances of being cited in AI-generated answers.',\n code: `{\n \"@context\": \"https://schema.org\",\n \"@type\": \"Article\",\n \"headline\": \"Article Title\",\n \"datePublished\": \"2025-01-01\",\n \"dateModified\": \"2025-01-02\",\n \"author\": { \"@type\": \"Person\", \"name\": \"Author Name\" }\n}`,\n },\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext, PageContext } from '../../check-context';\nimport { flattenJsonLd } from '../../parser';\n\nfunction matchesType(schema: Record<string, unknown>, type: string): boolean {\n const t = schema['@type'];\n if (typeof t === 'string') return t === type;\n if (Array.isArray(t)) return t.includes(type);\n return false;\n}\n\nfunction extractHeadings(page: PageContext): string[] {\n const headings: string[] = [];\n page.$('h1, h2, h3, h4, h5, h6').each((_, el) => {\n const text = page.$(el).text().trim();\n if (text) headings.push(text);\n });\n return headings;\n}\n\nfunction hasQuestionHeadings(page: PageContext): boolean {\n return extractHeadings(page).some((h) => h.endsWith('?'));\n}\n\nexport class FaqPageSchemaAudit extends Audit {\n static override meta: AuditMeta = {\n id: '3.7',\n category: 'structured-data',\n title: 'FAQPage schema',\n failureTitle: 'FAQPage schema',\n description:\n 'AI answer engines like Perplexity and Google SGE extract FAQ-structured content with higher confidence for direct answers. FAQPage schema makes your Q&A content machine-readable, giving it priority in AI-generated responses over unstructured text.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'AI answer engines like Perplexity and Google SGE give priority to FAQ-structured content for direct answers. Without FAQPage schema, your Q&A content is treated as unstructured text and is less likely to be surfaced as a featured answer in AI-generated responses.',\n fix: 'Add FAQPage JSON-LD to every page that contains question-answer content. Each question should be a Question type with an acceptedAnswer of type Answer.',\n code: `{\n \"@context\": \"https://schema.org\",\n \"@type\": \"FAQPage\",\n \"mainEntity\": [\n {\n \"@type\": \"Question\",\n \"name\": \"What is your return policy?\",\n \"acceptedAnswer\": {\n \"@type\": \"Answer\",\n \"text\": \"We offer a 30-day money-back guarantee on all purchases.\"\n }\n }\n ]\n}`,\n effort: 'easy',\n docsUrl: 'https://schema.org/FAQPage',\n tags: ['json-ld', 'schema', 'faq', 'content'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const pagesWithQuestions = ctx.pages.filter((p) => hasQuestionHeadings(p));\n\n if (pagesWithQuestions.length === 0) {\n return this.warn(\n 'No pages with question-patterned headings detected to evaluate.',\n 'FAQPage schema on pages with question-patterned headings.',\n 'No question-patterned headings found.',\n {\n priority: 'low',\n description:\n 'AI answer engines like Perplexity and Google SGE extract FAQ-structured content with high confidence for direct answers. Consider adding FAQ sections with question-formatted headings and FAQPage schema to your content pages.',\n code: `{\n \"@context\": \"https://schema.org\",\n \"@type\": \"FAQPage\",\n \"mainEntity\": [{\n \"@type\": \"Question\",\n \"name\": \"What is ...?\",\n \"acceptedAnswer\": { \"@type\": \"Answer\", \"text\": \"...\" }\n }]\n}`,\n },\n );\n }\n\n const pagesWithFaq = pagesWithQuestions.filter((p) => {\n const schemas = flattenJsonLd(p.structuredData ?? p.jsonLd);\n return schemas.some((s) => matchesType(s as Record<string, unknown>, 'FAQPage'));\n });\n\n const allHave = pagesWithFaq.length === pagesWithQuestions.length;\n const someHave = pagesWithFaq.length > 0;\n\n if (allHave) {\n return this.pass(\n `FAQPage schema found on all ${pagesWithQuestions.length} page(s) with question headings.`,\n 'FAQPage schema on pages with question-patterned headings.',\n `${pagesWithFaq.length}/${pagesWithQuestions.length} pages with FAQPage schema`,\n );\n }\n\n if (someHave) {\n return this.warn(\n `FAQPage schema found on ${pagesWithFaq.length} of ${pagesWithQuestions.length} page(s) with question headings.`,\n 'FAQPage schema on pages with question-patterned headings.',\n `${pagesWithFaq.length}/${pagesWithQuestions.length} pages with FAQPage schema`,\n {\n priority: 'medium',\n description:\n 'AI answer engines like Perplexity and Google SGE extract FAQ-structured content with higher confidence for direct answers. FAQPage schema makes your Q&A content machine-readable, giving it priority in AI-generated responses over unstructured text.',\n code: `{\n \"@context\": \"https://schema.org\",\n \"@type\": \"FAQPage\",\n \"mainEntity\": [{\n \"@type\": \"Question\",\n \"name\": \"What is ...?\",\n \"acceptedAnswer\": { \"@type\": \"Answer\", \"text\": \"...\" }\n }]\n}`,\n },\n );\n }\n\n return this.fail(\n `No FAQPage schema found on ${pagesWithQuestions.length} page(s) with question headings.`,\n 'FAQPage schema on pages with question-patterned headings.',\n `${pagesWithFaq.length}/${pagesWithQuestions.length} pages with FAQPage schema`,\n {\n priority: 'medium',\n description:\n 'AI answer engines like Perplexity and Google SGE extract FAQ-structured content with higher confidence for direct answers. FAQPage schema makes your Q&A content machine-readable, giving it priority in AI-generated responses over unstructured text.',\n code: `{\n \"@context\": \"https://schema.org\",\n \"@type\": \"FAQPage\",\n \"mainEntity\": [{\n \"@type\": \"Question\",\n \"name\": \"What is ...?\",\n \"acceptedAnswer\": { \"@type\": \"Answer\", \"text\": \"...\" }\n }]\n}`,\n },\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\nimport { flattenJsonLd } from '../../parser';\n\nfunction matchesAnyType(schema: Record<string, unknown>, types: string[]): boolean {\n return types.some((t) => {\n const st = schema['@type'];\n if (typeof st === 'string') return st === t;\n if (Array.isArray(st)) return st.includes(t);\n return false;\n });\n}\n\nfunction allSchemas(ctx: CheckContext): object[] {\n return ctx.pages.flatMap((p) => flattenJsonLd(p.structuredData ?? p.jsonLd));\n}\n\nfunction hasProps(obj: Record<string, unknown>, keys: string[]): string[] {\n return keys.filter((k) => !obj[k]);\n}\n\nexport class ServiceProductSchemaAudit extends Audit {\n static override meta: AuditMeta = {\n id: '3.8',\n category: 'structured-data',\n title: 'Service/Product schema',\n failureTitle: 'Service/Product schema',\n description:\n 'AI agents use Service/Product schema to understand what you offer, who provides it, and how to describe it to users. Without it, agents must infer your offerings from unstructured text, which leads to inaccurate or incomplete descriptions in AI-generated recommendations.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n applicablePageTypes: ['product'],\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'Without Service or Product schema, AI agents must infer your offerings from unstructured text. This leads to inaccurate or incomplete descriptions in AI-generated recommendations, and your services may be entirely overlooked when agents compare options for users.',\n fix: 'Add Service or Product JSON-LD to pages describing your offerings. Include name, description, and provider (nested Organization) at minimum.',\n code: `{\n \"@context\": \"https://schema.org\",\n \"@type\": \"Service\",\n \"name\": \"Your Service Name\",\n \"description\": \"A clear description of what this service provides.\",\n \"provider\": {\n \"@type\": \"Organization\",\n \"name\": \"Your Company\"\n }\n}`,\n effort: 'easy',\n docsUrl: 'https://schema.org/Service',\n tags: ['json-ld', 'schema', 'service', 'product', 'ecommerce'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const schemas = allSchemas(ctx);\n const serviceProducts = schemas.filter((s) =>\n matchesAnyType(s as Record<string, unknown>, ['Service', 'Product']),\n );\n\n if (serviceProducts.length === 0) {\n return this.fail(\n 'No Service or Product schema found.',\n 'Service or Product schema with name, description, and provider.',\n 'None',\n {\n priority: 'medium',\n description:\n 'AI agents use Service/Product schema to understand what you offer, who provides it, and how to describe it to users. Without it, agents must infer your offerings from unstructured text, which leads to inaccurate or incomplete descriptions in AI-generated recommendations.',\n code: `{\n \"@context\": \"https://schema.org\",\n \"@type\": \"Service\",\n \"name\": \"Service Name\",\n \"description\": \"Service description\",\n \"provider\": { \"@type\": \"Organization\", \"name\": \"Your Company\" }\n}`,\n },\n );\n }\n\n const requiredProps = ['name', 'description', 'provider'];\n const first = serviceProducts[0] as Record<string, unknown>;\n const missing = hasProps(first, requiredProps);\n const valid = missing.length === 0;\n\n if (valid) {\n return this.pass(\n `Service/Product schema found with name, description, and provider.`,\n 'Service or Product schema with name, description, and provider.',\n `Complete Service/Product schema (${serviceProducts.length} total)`,\n );\n }\n\n return this.warn(\n `Service/Product schema found but missing: ${missing.join(', ')}.`,\n 'Service or Product schema with name, description, and provider.',\n `Service/Product schema missing ${missing.join(', ')}`,\n {\n priority: 'medium',\n description: `AI agents use Service/Product schema properties to accurately describe your offerings to users. Missing properties (${missing.join(', ')}) mean agents cannot fully represent your service in AI-generated recommendations. Add them to your existing schema.`,\n code: `{\n \"@type\": \"Service\",\n \"name\": \"Service Name\",\n \"description\": \"Service description\",\n \"provider\": { \"@type\": \"Organization\", \"name\": \"Your Company\" }\n}`,\n },\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\nimport { flattenJsonLd } from '../../parser';\n\nfunction allSchemas(ctx: CheckContext): object[] {\n return ctx.pages.flatMap((p) => flattenJsonLd(p.structuredData ?? p.jsonLd));\n}\n\nexport class SpeakableSchemaAudit extends Audit {\n static override meta: AuditMeta = {\n id: '3.9',\n category: 'structured-data',\n title: 'Speakable schema',\n failureTitle: 'Speakable schema',\n description:\n 'Voice-based AI agents (Google Assistant, Alexa, Siri) use the speakable property to identify which parts of your page to read aloud. Without it, voice agents must guess which content to vocalize, often choosing poorly. Add cssSelector references to your most important content sections.',\n scoreDisplayMode: 'binary',\n weight: 1.0,\n defaultPriority: 'low',\n guidance: {\n impact:\n 'Voice-based AI agents (Google Assistant, Alexa, Siri) use the speakable property to identify which parts of your page to read aloud. Without it, voice agents guess which content to vocalize, often choosing navigation text or boilerplate instead of your key content.',\n fix: 'Add a speakable property with a SpeakableSpecification type to your Article, WebPage, or other content schema. Use cssSelector to point to your most important content elements.',\n code: `{\n \"@context\": \"https://schema.org\",\n \"@type\": \"WebPage\",\n \"name\": \"Page Title\",\n \"speakable\": {\n \"@type\": \"SpeakableSpecification\",\n \"cssSelector\": [\".article-title\", \".article-summary\"]\n }\n}`,\n effort: 'easy',\n docsUrl: 'https://schema.org/speakable',\n tags: ['json-ld', 'schema', 'voice', 'accessibility', 'speakable'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const schemas = allSchemas(ctx);\n const withSpeakable = schemas.filter((s) => {\n const obj = s as Record<string, unknown>;\n const sp = obj['speakable'] as Record<string, unknown> | undefined;\n return sp && Array.isArray(sp['cssSelector']);\n });\n\n const found = withSpeakable.length > 0;\n\n if (found) {\n return this.pass(\n `Speakable property with cssSelector array found on ${withSpeakable.length} schema(s).`,\n 'Speakable property with cssSelector array on at least one schema.',\n `${withSpeakable.length} schema(s) with speakable`,\n );\n }\n\n return this.fail(\n 'No speakable property with cssSelector array found.',\n 'Speakable property with cssSelector array on at least one schema.',\n 'None',\n {\n priority: 'low',\n description:\n 'Voice-based AI agents (Google Assistant, Alexa, Siri) use the speakable property to identify which parts of your page to read aloud. Without it, voice agents must guess which content to vocalize, often choosing poorly. Add cssSelector references to your most important content sections.',\n code: `\"speakable\": {\n \"@type\": \"SpeakableSpecification\",\n \"cssSelector\": [\".article-title\", \".article-summary\"]\n}`,\n },\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\nimport { flattenJsonLd } from '../../parser';\n\nfunction matchesAnyType(schema: Record<string, unknown>, types: string[]): boolean {\n return types.some((t) => {\n const st = schema['@type'];\n if (typeof st === 'string') return st === t;\n if (Array.isArray(st)) return st.includes(t);\n return false;\n });\n}\n\nfunction allSchemas(ctx: CheckContext): object[] {\n return ctx.pages.flatMap((p) => flattenJsonLd(p.structuredData ?? p.jsonLd));\n}\n\nexport class PotentialActionAudit extends Audit {\n static override meta: AuditMeta = {\n id: '3.10',\n category: 'structured-data',\n title: 'potentialAction on service pages',\n failureTitle: 'potentialAction on service pages',\n description:\n 'AI agents use potentialAction to understand what actions users can take on your site (order, book, contact). This enables agentic workflows where ChatGPT or Claude can guide users directly to the right action URL instead of just describing your service.',\n scoreDisplayMode: 'binary',\n weight: 1.0,\n applicablePageTypes: ['homepage', 'product'],\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'Without potentialAction schema, AI agents cannot determine what actions users can take on your site (order, book, contact). This prevents agentic workflows where ChatGPT or Claude could guide users directly to the right action URL, reducing conversion from AI-driven traffic.',\n fix: 'Add a potentialAction property to your Organization or Service schema with a ContactAction, OrderAction, or BookAction type and a target URL.',\n code: `{\n \"@context\": \"https://schema.org\",\n \"@type\": \"Organization\",\n \"name\": \"Your Company\",\n \"potentialAction\": {\n \"@type\": \"OrderAction\",\n \"target\": \"https://yoursite.com/order\"\n }\n}`,\n effort: 'easy',\n docsUrl: 'https://schema.org/potentialAction',\n tags: ['json-ld', 'schema', 'actions', 'agentic-commerce'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const actionTypes = ['ContactAction', 'OrderAction', 'BookAction'];\n const schemas = allSchemas(ctx);\n\n const withAction = schemas.filter((s) => {\n const obj = s as Record<string, unknown>;\n const action = obj['potentialAction'];\n if (!action) return false;\n\n const actions = Array.isArray(action) ? action : [action];\n return actions.some(\n (a) =>\n a && typeof a === 'object' && matchesAnyType(a as Record<string, unknown>, actionTypes),\n );\n });\n\n const found = withAction.length > 0;\n\n if (found) {\n return this.pass(\n `potentialAction (ContactAction/OrderAction/BookAction) found on ${withAction.length} schema(s).`,\n 'At least one page with potentialAction (ContactAction, OrderAction, or BookAction).',\n `${withAction.length} schema(s) with qualifying potentialAction`,\n );\n }\n\n return this.fail(\n 'No potentialAction with ContactAction, OrderAction, or BookAction found.',\n 'At least one page with potentialAction (ContactAction, OrderAction, or BookAction).',\n 'None',\n {\n priority: 'medium',\n description:\n 'AI agents use potentialAction to understand what actions users can take on your site (order, book, contact). This enables agentic workflows where ChatGPT or Claude can guide users directly to the right action URL instead of just describing your service.',\n code: `\"potentialAction\": {\n \"@type\": \"OrderAction\",\n \"target\": \"https://yoursite.com/order\"\n}`,\n },\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext, PageContext } from '../../check-context';\nimport { flattenJsonLd } from '../../parser';\n\nfunction matchesType(schema: Record<string, unknown>, type: string): boolean {\n const t = schema['@type'];\n if (typeof t === 'string') return t === type;\n if (Array.isArray(t)) return t.includes(type);\n return false;\n}\n\nfunction extractHeadings(page: PageContext): string[] {\n const headings: string[] = [];\n page.$('h1, h2, h3, h4, h5, h6').each((_, el) => {\n const text = page.$(el).text().trim();\n if (text) headings.push(text);\n });\n return headings;\n}\n\nfunction hasSequentialNumberedHeadings(page: PageContext): boolean {\n const headings = extractHeadings(page);\n let seqCount = 0;\n let expectedNum = 1;\n for (const h of headings) {\n const match = h.match(/^(?:step\\s+)?(\\d+)[.):\\s]/i);\n if (match && parseInt(match[1], 10) === expectedNum) {\n seqCount++;\n expectedNum++;\n }\n }\n return seqCount >= 2;\n}\n\nexport class HowToSchemaAudit extends Audit {\n static override meta: AuditMeta = {\n id: '3.11',\n category: 'structured-data',\n title: 'HowTo schema',\n failureTitle: 'HowTo schema',\n description:\n 'AI agents use HowTo schema to present step-by-step instructions as structured answers. Without it, agents must parse your numbered headings heuristically, which often breaks step ordering or misses steps entirely.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n applicablePageTypes: ['content'],\n defaultPriority: 'low',\n guidance: {\n impact:\n 'Without HowTo schema, AI agents must heuristically parse your numbered headings to extract step-by-step instructions. This often results in broken step ordering, missed steps, or incomplete instructions in AI-generated answers, reducing your content utility.',\n fix: 'Add HowTo JSON-LD to pages with step-by-step instructions. Include a step array with HowToStep items, each containing name and text properties.',\n code: `{\n \"@context\": \"https://schema.org\",\n \"@type\": \"HowTo\",\n \"name\": \"How to set up your account\",\n \"step\": [\n { \"@type\": \"HowToStep\", \"name\": \"Create an account\", \"text\": \"Visit the signup page and fill in your details.\" },\n { \"@type\": \"HowToStep\", \"name\": \"Verify your email\", \"text\": \"Click the link in the confirmation email.\" }\n ]\n}`,\n effort: 'easy',\n docsUrl: 'https://schema.org/HowTo',\n tags: ['json-ld', 'schema', 'content', 'how-to', 'instructions'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const pagesWithSteps = ctx.pages.filter((p) => hasSequentialNumberedHeadings(p));\n\n if (pagesWithSteps.length === 0) {\n return this.warn(\n 'No pages with sequential numbered headings detected to evaluate.',\n 'HowTo schema with step array on pages with sequential numbered headings.',\n 'No sequential numbered headings found.',\n {\n priority: 'low',\n description:\n 'AI agents use HowTo schema to present step-by-step instructions as structured answers. If your content includes processes or tutorials, add HowTo JSON-LD so agents can walk users through steps one at a time.',\n code: `{\n \"@context\": \"https://schema.org\",\n \"@type\": \"HowTo\",\n \"name\": \"How to ...\",\n \"step\": [\n { \"@type\": \"HowToStep\", \"name\": \"Step 1\", \"text\": \"...\" },\n { \"@type\": \"HowToStep\", \"name\": \"Step 2\", \"text\": \"...\" }\n ]\n}`,\n },\n );\n }\n\n const pagesWithHowTo = pagesWithSteps.filter((p) => {\n const schemas = flattenJsonLd(p.structuredData ?? p.jsonLd);\n return schemas.some((s) => {\n const obj = s as Record<string, unknown>;\n return matchesType(obj, 'HowTo') && Array.isArray(obj['step']);\n });\n });\n\n const allHave = pagesWithHowTo.length === pagesWithSteps.length;\n const someHave = pagesWithHowTo.length > 0;\n\n if (allHave) {\n return this.pass(\n `HowTo schema with steps found on all ${pagesWithSteps.length} page(s) with sequential headings.`,\n 'HowTo schema with step array on pages with sequential numbered headings.',\n `${pagesWithHowTo.length}/${pagesWithSteps.length} pages with HowTo schema`,\n );\n }\n\n if (someHave) {\n return this.warn(\n `HowTo schema found on ${pagesWithHowTo.length} of ${pagesWithSteps.length} page(s) with sequential headings.`,\n 'HowTo schema with step array on pages with sequential numbered headings.',\n `${pagesWithHowTo.length}/${pagesWithSteps.length} pages with HowTo schema`,\n {\n priority: 'low',\n description:\n 'AI agents use HowTo schema to present step-by-step instructions as structured answers. Without it, agents must parse your numbered headings heuristically, which often breaks step ordering or misses steps entirely.',\n code: `{\n \"@context\": \"https://schema.org\",\n \"@type\": \"HowTo\",\n \"name\": \"How to ...\",\n \"step\": [\n { \"@type\": \"HowToStep\", \"name\": \"Step 1\", \"text\": \"...\" },\n { \"@type\": \"HowToStep\", \"name\": \"Step 2\", \"text\": \"...\" }\n ]\n}`,\n },\n );\n }\n\n return this.fail(\n `No HowTo schema found on ${pagesWithSteps.length} page(s) with sequential headings.`,\n 'HowTo schema with step array on pages with sequential numbered headings.',\n `${pagesWithHowTo.length}/${pagesWithSteps.length} pages with HowTo schema`,\n {\n priority: 'low',\n description:\n 'AI agents use HowTo schema to present step-by-step instructions as structured answers. Without it, agents must parse your numbered headings heuristically, which often breaks step ordering or misses steps entirely.',\n code: `{\n \"@context\": \"https://schema.org\",\n \"@type\": \"HowTo\",\n \"name\": \"How to ...\",\n \"step\": [\n { \"@type\": \"HowToStep\", \"name\": \"Step 1\", \"text\": \"...\" },\n { \"@type\": \"HowToStep\", \"name\": \"Step 2\", \"text\": \"...\" }\n ]\n}`,\n },\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext, PageContext } from '../../check-context';\nimport { flattenJsonLd } from '../../parser';\n\nfunction matchesAnyType(schema: Record<string, unknown>, types: string[]): boolean {\n return types.some((t) => {\n const st = schema['@type'];\n if (typeof st === 'string') return st === t;\n if (Array.isArray(st)) return st.includes(t);\n return false;\n });\n}\n\nfunction allSchemas(ctx: CheckContext): object[] {\n return ctx.pages.flatMap((p) => flattenJsonLd(p.structuredData ?? p.jsonLd));\n}\n\n/** A structured PostalAddress block (JSON-LD, microdata, or RDFa). */\nfunction hasPostalAddressBlock(page: PageContext): boolean {\n const schemas = flattenJsonLd(page.structuredData ?? page.jsonLd);\n if (schemas.some((s) => matchesAnyType(s as Record<string, unknown>, ['PostalAddress']))) {\n return true;\n }\n return page.$('[itemtype*=\"PostalAddress\"]').length > 0;\n}\n\n/** A link/CTA that points to a store locator or physical store locations. */\nfunction hasStoreLocatorLink(page: PageContext): boolean {\n let found = false;\n page.$('a[href]').each((_, el) => {\n if (found) return;\n /* v8 ignore next */\n const href = (page.$(el).attr('href') ?? '').toLowerCase();\n const text = page.$(el).text().toLowerCase();\n if (\n /store-?locator|store-?finder|find-a-?store|find-a-?location|where-to-buy|\\/stores?(\\/|$|\\?)|\\/locations?(\\/|$|\\?)/i.test(\n href,\n ) ||\n /\\bstore locator\\b|\\bfind a store\\b|\\bstore finder\\b|\\bour locations\\b|\\bfind a location\\b|\\bwhere to buy\\b/i.test(\n text,\n )\n ) {\n found = true;\n }\n });\n return found;\n}\n\n/**\n * Real physical-location signal: a structured PostalAddress AND a\n * store-locator/locations link co-occurring on the same page. The previous\n * heuristic flagged any page containing a 5-digit number (e.g. an order total\n * or a zip in a footer newsletter form), over-triggering this audit on\n * online-only DTC stores that have no storefront.\n */\nfunction hasPhysicalLocationSignals(page: PageContext): boolean {\n return hasPostalAddressBlock(page) && hasStoreLocatorLink(page);\n}\n\nexport class LocalBusinessSchemaAudit extends Audit {\n static override meta: AuditMeta = {\n id: '3.12',\n category: 'structured-data',\n title: 'LocalBusiness/ProfessionalService schema',\n failureTitle: 'LocalBusiness/ProfessionalService schema',\n description:\n 'AI agents use LocalBusiness schema to answer location-based queries like \"find a [service] near me.\" Without it, your business is invisible to location-aware AI systems. Add address, telephone, and openingHours to help agents provide accurate local recommendations.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n applicablePageTypes: ['homepage'],\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'Without LocalBusiness schema, your business is invisible to location-aware AI systems. AI agents cannot answer \"find a [service] near me\" queries with your business, and your address, phone number, and hours will not appear in AI-generated local recommendations.',\n fix: 'Add LocalBusiness or ProfessionalService JSON-LD to your homepage. Include name, address (PostalAddress), telephone, and openingHours.',\n code: `{\n \"@context\": \"https://schema.org\",\n \"@type\": \"LocalBusiness\",\n \"name\": \"Your Business\",\n \"address\": {\n \"@type\": \"PostalAddress\",\n \"streetAddress\": \"123 Main St\",\n \"addressLocality\": \"City\",\n \"addressRegion\": \"ST\",\n \"postalCode\": \"12345\"\n },\n \"telephone\": \"+1-555-555-5555\",\n \"openingHours\": \"Mo-Fr 09:00-17:00\"\n}`,\n effort: 'easy',\n docsUrl: 'https://schema.org/LocalBusiness',\n tags: ['json-ld', 'schema', 'local-business', 'location'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const pagesWithLocation = ctx.pages.filter((p) => hasPhysicalLocationSignals(p));\n\n if (pagesWithLocation.length === 0) {\n return this.notApplicable(\n 'No physical store signals detected (no PostalAddress block paired with a store-locator link).',\n 'LocalBusiness or ProfessionalService schema if site has physical location indicators.',\n 'No physical location indicators found.',\n );\n }\n\n const schemas = allSchemas(ctx);\n const localSchemas = schemas.filter((s) =>\n matchesAnyType(s as Record<string, unknown>, ['LocalBusiness', 'ProfessionalService']),\n );\n\n const found = localSchemas.length > 0;\n\n if (found) {\n return this.pass(\n `LocalBusiness/ProfessionalService schema found (${localSchemas.length} instance(s)).`,\n 'LocalBusiness or ProfessionalService schema if site has physical location indicators.',\n `${localSchemas.length} LocalBusiness/ProfessionalService schema(s)`,\n );\n }\n\n return this.fail(\n 'Physical location indicators detected but no LocalBusiness or ProfessionalService schema found.',\n 'LocalBusiness or ProfessionalService schema if site has physical location indicators.',\n 'None',\n {\n priority: 'medium',\n description:\n 'AI agents use LocalBusiness schema to answer location-based queries like \"find a [service] near me.\" Without it, your business is invisible to location-aware AI systems. Add address, telephone, and openingHours to help agents provide accurate local recommendations.',\n code: `{\n \"@context\": \"https://schema.org\",\n \"@type\": \"LocalBusiness\",\n \"name\": \"Business Name\",\n \"address\": { \"@type\": \"PostalAddress\", \"streetAddress\": \"123 Main St\", \"addressLocality\": \"City\", \"addressRegion\": \"ST\", \"postalCode\": \"12345\" },\n \"telephone\": \"+1-555-555-5555\"\n}`,\n },\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext, PageContext } from '../../check-context';\nimport { flattenJsonLd } from '../../parser';\n\nfunction matchesAnyType(schema: Record<string, unknown>, types: string[]): boolean {\n return types.some((t) => {\n const st = schema['@type'];\n if (typeof st === 'string') return st === t;\n if (Array.isArray(st)) return st.includes(t);\n return false;\n });\n}\n\nfunction allSchemas(ctx: CheckContext): object[] {\n return ctx.pages.flatMap((p) => flattenJsonLd(p.structuredData ?? p.jsonLd));\n}\n\nfunction hasTestimonialContent(page: PageContext): boolean {\n const body = page.$('body').text().toLowerCase();\n /* v8 ignore next */\n const html = page.$('body').html()?.toLowerCase() ?? '';\n const textPatterns = [\n /\\btestimonial/i,\n /\\breview/i,\n /\\brating/i,\n /\\bstars?\\b/i,\n /\\bcustomer\\s+feedback\\b/i,\n ];\n const classPatterns = [/class=\"[^\"]*testimonial/i, /class=\"[^\"]*review/i, /class=\"[^\"]*rating/i];\n return textPatterns.some((p) => p.test(body)) || classPatterns.some((p) => p.test(html));\n}\n\nexport class ReviewSchemaAudit extends Audit {\n static override meta: AuditMeta = {\n id: '3.13',\n category: 'structured-data',\n title: 'Review/AggregateRating schema',\n failureTitle: 'Review/AggregateRating schema',\n description:\n 'AI agents use Review/AggregateRating schema as social proof when comparing options. When a user asks \"what is the best X?\", agents surface structured ratings from schema rather than parsing unstructured testimonial text. Add this schema to make your reviews machine-readable.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n applicablePageTypes: ['homepage', 'product'],\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'When users ask AI agents \"what is the best X?\", agents surface structured ratings from Review/AggregateRating schema rather than parsing unstructured testimonial text. Without this schema, your customer reviews and social proof are invisible to AI-driven comparisons and recommendations.',\n fix: 'Add AggregateRating or Review JSON-LD to pages with testimonials or reviews. For aggregate ratings, include ratingValue and reviewCount. For individual reviews, include author, reviewRating, and reviewBody.',\n code: `{\n \"@context\": \"https://schema.org\",\n \"@type\": \"Product\",\n \"name\": \"Your Product\",\n \"aggregateRating\": {\n \"@type\": \"AggregateRating\",\n \"ratingValue\": \"4.8\",\n \"reviewCount\": \"150\"\n },\n \"review\": {\n \"@type\": \"Review\",\n \"author\": { \"@type\": \"Person\", \"name\": \"Customer Name\" },\n \"reviewRating\": { \"@type\": \"Rating\", \"ratingValue\": \"5\" },\n \"reviewBody\": \"Excellent product, highly recommend.\"\n }\n}`,\n effort: 'moderate',\n docsUrl: 'https://schema.org/AggregateRating',\n tags: ['json-ld', 'schema', 'reviews', 'ratings', 'social-proof'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const pagesWithTestimonials = ctx.pages.filter((p) => hasTestimonialContent(p));\n\n if (pagesWithTestimonials.length === 0) {\n return this.warn(\n 'No testimonial or review content detected to evaluate.',\n 'Review or AggregateRating schema on pages with testimonials or reviews.',\n 'No testimonial/review content found.',\n {\n priority: 'low',\n description:\n 'AI agents use Review and AggregateRating schema as trust signals when recommending products or services. If you have customer reviews or testimonials, marking them up with schema makes them available for AI-generated comparisons and recommendations.',\n code: `\"aggregateRating\": {\n \"@type\": \"AggregateRating\",\n \"ratingValue\": \"4.8\",\n \"reviewCount\": \"150\"\n}`,\n },\n );\n }\n\n const schemas = allSchemas(ctx);\n const reviewSchemas = schemas.filter((s) =>\n matchesAnyType(s as Record<string, unknown>, ['Review', 'AggregateRating']),\n );\n\n // Also check if any schema has aggregateRating or review property\n const schemasWithReviewProp = schemas.filter((s) => {\n const obj = s as Record<string, unknown>;\n return obj['aggregateRating'] || obj['review'];\n });\n\n const found = reviewSchemas.length > 0 || schemasWithReviewProp.length > 0;\n\n if (found) {\n return this.pass(\n 'Review or AggregateRating structured data found.',\n 'Review or AggregateRating schema on pages with testimonials or reviews.',\n `${reviewSchemas.length} Review/AggregateRating schema(s), ${schemasWithReviewProp.length} schema(s) with review properties`,\n );\n }\n\n return this.fail(\n 'Testimonial/review content detected but no Review or AggregateRating schema found.',\n 'Review or AggregateRating schema on pages with testimonials or reviews.',\n 'None',\n {\n priority: 'medium',\n description:\n 'AI agents use Review/AggregateRating schema as social proof when comparing options. When a user asks \"what is the best X?\", agents surface structured ratings from schema rather than parsing unstructured testimonial text. Add this schema to make your reviews machine-readable.',\n code: `\"aggregateRating\": {\n \"@type\": \"AggregateRating\",\n \"ratingValue\": \"4.8\",\n \"reviewCount\": \"150\"\n}`,\n },\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\nimport { flattenJsonLd } from '../../parser';\n\nfunction matchesAnyType(schema: Record<string, unknown>, types: string[]): boolean {\n return types.some((t) => {\n const st = schema['@type'];\n if (typeof st === 'string') return st === t;\n if (Array.isArray(st)) return st.includes(t);\n return false;\n });\n}\n\nexport class OfferSchemaAudit extends Audit {\n static override meta: AuditMeta = {\n id: '3.14',\n category: 'structured-data',\n title: 'Offer schema on pricing pages',\n failureTitle: 'Offer schema on pricing pages',\n description:\n 'AI agents use Offer schema to answer pricing queries with exact numbers. Without price and priceCurrency in structured data, agents must scrape and guess pricing from page text, which often produces inaccurate or outdated results in AI-generated comparisons.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n applicablePageTypes: ['product'],\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'Without Offer schema on pricing pages, AI agents cannot answer \"how much does X cost?\" with exact numbers. Agents must scrape and guess pricing from page text, which frequently produces inaccurate or outdated results in AI-generated price comparisons.',\n fix: 'Add Offer or AggregateOffer JSON-LD to your pricing pages. Include price, priceCurrency, and optionally availability and priceValidUntil.',\n code: `{\n \"@context\": \"https://schema.org\",\n \"@type\": \"Offer\",\n \"name\": \"Pro Plan\",\n \"price\": \"99.00\",\n \"priceCurrency\": \"USD\",\n \"availability\": \"https://schema.org/InStock\",\n \"priceValidUntil\": \"2026-12-31\"\n}`,\n effort: 'easy',\n docsUrl: 'https://schema.org/Offer',\n tags: ['json-ld', 'schema', 'pricing', 'ecommerce'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n // Offer schema lives on product/pricing pages. Shopify and most ecommerce\n // platforms serve products under /products/, not /pricing/ or /plans/, so a\n // URL gate produces false \"not applicable\" verdicts. Gate on the detected\n // product page type instead, which already covers SaaS pricing pages.\n const productPages = ctx.pages.filter((p) => p.pageType === 'product');\n\n if (productPages.length === 0) {\n return this.notApplicable(\n 'No product pages scanned to evaluate Offer schema.',\n 'Offer schema with price and priceCurrency on product pages.',\n 'No product pages detected.',\n );\n }\n\n const pagesWithOffer = productPages.filter((p) => {\n const schemas = flattenJsonLd(p.structuredData ?? p.jsonLd);\n\n // Check for standalone Offer schemas\n const hasOfferSchema = schemas.some((s) =>\n matchesAnyType(s as Record<string, unknown>, ['Offer', 'AggregateOffer']),\n );\n\n // Check for offer/offers property on other schemas\n const hasOfferProp = schemas.some((s) => {\n const obj = s as Record<string, unknown>;\n const offer = obj['offers'] || obj['offer'];\n if (!offer) return false;\n const offers = Array.isArray(offer) ? offer : [offer];\n return offers.some((o) => {\n const offerObj = o as Record<string, unknown>;\n return offerObj['price'] !== undefined && offerObj['priceCurrency'];\n });\n });\n\n if (hasOfferSchema) {\n const first = schemas.find((s) =>\n matchesAnyType(s as Record<string, unknown>, ['Offer', 'AggregateOffer']),\n ) as Record<string, unknown>;\n return first && first['price'] !== undefined && !!first['priceCurrency'];\n }\n\n return hasOfferProp;\n });\n\n const allHave = pagesWithOffer.length === productPages.length;\n const someHave = pagesWithOffer.length > 0;\n\n if (allHave) {\n return this.pass(\n `Offer schema with price and priceCurrency found on all ${productPages.length} product page(s).`,\n 'Offer schema with price and priceCurrency on product pages.',\n `${pagesWithOffer.length}/${productPages.length} product pages with Offer schema`,\n );\n }\n\n if (someHave) {\n return this.warn(\n `Offer schema found on ${pagesWithOffer.length} of ${productPages.length} product page(s).`,\n 'Offer schema with price and priceCurrency on product pages.',\n `${pagesWithOffer.length}/${productPages.length} product pages with Offer schema`,\n {\n priority: 'medium',\n description:\n 'AI agents use Offer schema to answer pricing queries with exact numbers. Without price and priceCurrency in structured data, agents must scrape and guess pricing from page text, which often produces inaccurate or outdated results in AI-generated comparisons.',\n code: `{\n \"@context\": \"https://schema.org\",\n \"@type\": \"Offer\",\n \"price\": \"99.00\",\n \"priceCurrency\": \"USD\",\n \"name\": \"Plan Name\"\n}`,\n },\n );\n }\n\n return this.fail(\n `No Offer schema found on ${productPages.length} product page(s).`,\n 'Offer schema with price and priceCurrency on product pages.',\n `${pagesWithOffer.length}/${productPages.length} product pages with Offer schema`,\n {\n priority: 'medium',\n description:\n 'AI agents use Offer schema to answer pricing queries with exact numbers. Without price and priceCurrency in structured data, agents must scrape and guess pricing from page text, which often produces inaccurate or outdated results in AI-generated comparisons.',\n code: `{\n \"@context\": \"https://schema.org\",\n \"@type\": \"Offer\",\n \"price\": \"99.00\",\n \"priceCurrency\": \"USD\",\n \"name\": \"Plan Name\"\n}`,\n },\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\nimport { flattenJsonLd } from '../../parser';\n\nfunction matchesType(schema: Record<string, unknown>, type: string): boolean {\n const t = schema['@type'];\n if (typeof t === 'string') return t === type;\n if (Array.isArray(t)) return t.includes(type);\n return false;\n}\n\nfunction matchesAnyType(schema: Record<string, unknown>, types: string[]): boolean {\n return types.some((t) => matchesType(schema, t));\n}\n\nfunction allSchemas(ctx: CheckContext): object[] {\n return ctx.pages.flatMap((p) => flattenJsonLd(p.structuredData ?? p.jsonLd));\n}\n\nfunction hasProps(obj: Record<string, unknown>, keys: string[]): string[] {\n return keys.filter((k) => !obj[k]);\n}\n\nexport class AuthorSchemaAudit extends Audit {\n static override meta: AuditMeta = {\n id: '3.15',\n category: 'structured-data',\n title: 'Author schema with credentials',\n failureTitle: 'Author schema with credentials',\n description:\n 'AI systems assign higher confidence to content from named experts with verifiable credentials. Person schema with jobTitle, sameAs, and affiliation lets AI agents cross-reference author identity across platforms, boosting your content in RAG trust scoring.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n applicablePageTypes: ['content'],\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'AI systems assign higher trust to content from named experts with verifiable credentials. Without Person schema containing jobTitle, sameAs, and affiliation, AI agents cannot cross-reference your author identity across platforms, lowering your content ranking in RAG trust scoring and reducing citation likelihood.',\n fix: 'Add or enhance Person schema on author pages and within Article author properties. Include name, jobTitle, sameAs (linking to LinkedIn, Twitter, etc.), and affiliation with a nested Organization.',\n code: `{\n \"@context\": \"https://schema.org\",\n \"@type\": \"Person\",\n \"name\": \"Jane Smith\",\n \"jobTitle\": \"Senior Product Engineer\",\n \"sameAs\": [\n \"https://linkedin.com/in/janesmith\",\n \"https://twitter.com/janesmith\"\n ],\n \"affiliation\": {\n \"@type\": \"Organization\",\n \"name\": \"Your Company\"\n }\n}`,\n effort: 'easy',\n docsUrl: 'https://schema.org/Person',\n tags: ['json-ld', 'schema', 'author', 'trust', 'E-E-A-T'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const schemas = allSchemas(ctx);\n const personSchemas = schemas.filter((s) =>\n matchesType(s as Record<string, unknown>, 'Person'),\n );\n\n // Also check author properties on Article schemas (support single objects and arrays)\n const authorFromArticles: Record<string, unknown>[] = [];\n for (const s of schemas) {\n if (matchesAnyType(s as Record<string, unknown>, ['Article', 'NewsArticle', 'BlogPosting'])) {\n const author = (s as Record<string, unknown>)['author'];\n if (Array.isArray(author)) {\n for (const a of author) {\n if (a && typeof a === 'object' && !Array.isArray(a)) {\n authorFromArticles.push(a as Record<string, unknown>);\n }\n }\n } else if (author && typeof author === 'object') {\n authorFromArticles.push(author as Record<string, unknown>);\n }\n }\n }\n\n const allPersons = [\n ...personSchemas.map((s) => s as Record<string, unknown>),\n ...authorFromArticles,\n ];\n\n if (allPersons.length === 0) {\n return this.fail(\n 'No Person (author) schema found.',\n 'Person schema with name, jobTitle, sameAs, and affiliation.',\n 'None',\n {\n priority: 'medium',\n description:\n 'AI systems assign higher confidence to content from named experts with verifiable credentials. Person schema with jobTitle, sameAs, and affiliation lets AI agents cross-reference author identity across platforms, boosting your content in RAG trust scoring.',\n code: `{\n \"@context\": \"https://schema.org\",\n \"@type\": \"Person\",\n \"name\": \"Author Name\",\n \"jobTitle\": \"Senior Engineer\",\n \"sameAs\": [\"https://linkedin.com/in/author\", \"https://twitter.com/author\"],\n \"affiliation\": { \"@type\": \"Organization\", \"name\": \"Company\" }\n}`,\n },\n );\n }\n\n const requiredProps = ['name', 'jobTitle', 'sameAs', 'affiliation'];\n const bestPerson = allPersons.reduce((best, p) => {\n const bestMissing = hasProps(best, requiredProps).length;\n const currentMissing = hasProps(p, requiredProps).length;\n return currentMissing < bestMissing ? p : best;\n }, allPersons[0]);\n\n const missing = hasProps(bestPerson, requiredProps);\n const complete = missing.length === 0;\n\n if (complete) {\n return this.pass(\n 'Person schema found with name, jobTitle, sameAs, and affiliation.',\n 'Person schema with name, jobTitle, sameAs, and affiliation.',\n `Complete Person schema (${allPersons.length} total)`,\n );\n }\n\n return this.warn(\n `Person schema found but missing: ${missing.join(', ')}.`,\n 'Person schema with name, jobTitle, sameAs, and affiliation.',\n `Person schema missing ${missing.join(', ')}`,\n {\n priority: 'medium',\n description: `AI systems cross-reference author identity across platforms for trust scoring. Missing properties (${missing.join(', ')}) prevent agents from verifying author credentials, reducing confidence in your content. Add them to your Person schema.`,\n code: `{\n \"@type\": \"Person\",\n \"name\": \"Author Name\",\n \"jobTitle\": \"Senior Engineer\",\n \"sameAs\": [\"https://linkedin.com/in/author\"],\n \"affiliation\": { \"@type\": \"Organization\", \"name\": \"Company\" }\n}`,\n },\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\nimport { flattenJsonLd } from '../../parser';\n\nfunction matchesAnyType(schema: Record<string, unknown>, types: string[]): boolean {\n return types.some((t) => {\n const st = schema['@type'];\n if (typeof st === 'string') return st === t;\n if (Array.isArray(st)) return st.includes(t);\n return false;\n });\n}\n\nfunction isConfirmationUrl(url: string): boolean {\n return /\\/(thank-?you|confirmation|success|order-complete)\\b/i.test(url);\n}\n\nexport class ActionSchemaAudit extends Audit {\n static override meta: AuditMeta = {\n id: '3.16',\n category: 'structured-data',\n title: 'ConfirmAction/ReserveAction schema',\n failureTitle: 'ConfirmAction/ReserveAction schema',\n description:\n 'AI agents use ConfirmAction/ReserveAction schema to complete transactions on behalf of users in agentic workflows. Without this schema on your confirmation pages, agents cannot programmatically verify that a booking or purchase was successful.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'low',\n guidance: {\n impact:\n 'Without ConfirmAction or ReserveAction schema on confirmation pages, AI agents cannot programmatically verify that a booking or purchase completed successfully. This breaks end-to-end agentic commerce workflows, forcing users back into manual checkout confirmation.',\n fix: 'Add a ConfirmAction or ReserveAction as a potentialAction on your thank-you/confirmation page JSON-LD. Include the target URL pointing to the confirmation endpoint.',\n code: `{\n \"@context\": \"https://schema.org\",\n \"@type\": \"WebPage\",\n \"potentialAction\": {\n \"@type\": \"ConfirmAction\",\n \"target\": \"https://yoursite.com/confirm\"\n }\n}`,\n effort: 'moderate',\n docsUrl: 'https://schema.org/ConfirmAction',\n tags: ['json-ld', 'schema', 'agentic-commerce', 'actions'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const confirmationPages = ctx.pages.filter((p) => isConfirmationUrl(p.url));\n\n if (confirmationPages.length === 0) {\n return this.warn(\n 'No thank-you or confirmation pages detected to evaluate.',\n 'ConfirmAction or ReserveAction schema on thank-you/confirmation pages.',\n 'No confirmation pages detected (URLs containing /thank-you/, /confirmation/, /success/).',\n {\n priority: 'low',\n description:\n 'If your site has booking or purchase flows, AI agents use ConfirmAction/ReserveAction schema to complete transactions on behalf of users. This enables end-to-end agentic workflows where the agent can confirm a booking without the user manually navigating forms.',\n code: `\"potentialAction\": {\n \"@type\": \"ConfirmAction\",\n \"target\": \"https://yoursite.com/confirm\"\n}`,\n },\n );\n }\n\n const actionTypes = ['ConfirmAction', 'ReserveAction'];\n\n const pagesWithAction = confirmationPages.filter((p) => {\n const schemas = flattenJsonLd(p.structuredData ?? p.jsonLd);\n\n // Check for standalone action schemas\n const hasActionSchema = schemas.some((s) =>\n matchesAnyType(s as Record<string, unknown>, actionTypes),\n );\n\n // Check for potentialAction property with these types\n const hasActionProp = schemas.some((s) => {\n const obj = s as Record<string, unknown>;\n const action = obj['potentialAction'];\n if (!action) return false;\n const actions = Array.isArray(action) ? action : [action];\n return actions.some(\n (a) =>\n a && typeof a === 'object' && matchesAnyType(a as Record<string, unknown>, actionTypes),\n );\n });\n\n return hasActionSchema || hasActionProp;\n });\n\n const allHave = pagesWithAction.length === confirmationPages.length;\n const someHave = pagesWithAction.length > 0;\n\n if (allHave) {\n return this.pass(\n `ConfirmAction/ReserveAction found on all ${confirmationPages.length} confirmation page(s).`,\n 'ConfirmAction or ReserveAction schema on thank-you/confirmation pages.',\n `${pagesWithAction.length}/${confirmationPages.length} confirmation pages with action schema`,\n );\n }\n\n if (someHave) {\n return this.warn(\n `ConfirmAction/ReserveAction found on ${pagesWithAction.length} of ${confirmationPages.length} confirmation page(s).`,\n 'ConfirmAction or ReserveAction schema on thank-you/confirmation pages.',\n `${pagesWithAction.length}/${confirmationPages.length} confirmation pages with action schema`,\n {\n priority: 'low',\n description:\n 'AI agents use ConfirmAction/ReserveAction schema to complete transactions on behalf of users in agentic workflows. Without this schema on your confirmation pages, agents cannot programmatically verify that a booking or purchase was successful.',\n code: `\"potentialAction\": {\n \"@type\": \"ConfirmAction\",\n \"target\": \"https://yoursite.com/confirm\"\n}`,\n },\n );\n }\n\n return this.fail(\n `No ConfirmAction/ReserveAction found on ${confirmationPages.length} confirmation page(s).`,\n 'ConfirmAction or ReserveAction schema on thank-you/confirmation pages.',\n `${pagesWithAction.length}/${confirmationPages.length} confirmation pages with action schema`,\n {\n priority: 'low',\n description:\n 'AI agents use ConfirmAction/ReserveAction schema to complete transactions on behalf of users in agentic workflows. Without this schema on your confirmation pages, agents cannot programmatically verify that a booking or purchase was successful.',\n code: `\"potentialAction\": {\n \"@type\": \"ConfirmAction\",\n \"target\": \"https://yoursite.com/confirm\"\n}`,\n },\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\nimport { flattenJsonLd } from '../../parser';\n\nfunction matchesAnyType(schema: Record<string, unknown>, types: string[]): boolean {\n return types.some((t) => {\n const st = schema['@type'];\n if (typeof st === 'string') return st === t;\n if (Array.isArray(st)) return st.includes(t);\n return false;\n });\n}\n\nexport class ProductIdentifiersAudit extends Audit {\n static override meta: AuditMeta = {\n id: '3.21',\n category: 'structured-data',\n title: 'Product identifiers (GTIN/UPC/MPN)',\n failureTitle: 'Product identifiers (GTIN/UPC/MPN)',\n description:\n 'AI agents use unique identifiers like GTIN, UPC, or MPN to de-duplicate products across different sources and confirm they are looking at the exact item the user wants. Without them, agents may confuse similar products or fail to find specific pricing.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n applicablePageTypes: ['product'],\n defaultPriority: 'high',\n guidance: {\n impact:\n 'Without unique identifiers (GTIN, UPC, MPN, or SKU), AI agents cannot de-duplicate your products across different sources or confirm they are looking at the exact item the user wants. This leads to product confusion, missed price-comparison opportunities, and lower visibility in AI shopping assistants.',\n fix: 'Add at least one unique product identifier to your Product JSON-LD. Use sku for internal IDs, gtin13 for barcodes, or mpn for manufacturer part numbers.',\n code: `{\n \"@context\": \"https://schema.org\",\n \"@type\": \"Product\",\n \"name\": \"Product Name\",\n \"sku\": \"SKU-123456\",\n \"gtin13\": \"1234567890123\",\n \"mpn\": \"MPN-7890\"\n}`,\n effort: 'easy',\n docsUrl: 'https://schema.org/Product',\n tags: ['json-ld', 'schema', 'product', 'ecommerce', 'identifiers'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const schemas = ctx.pages.flatMap((p) => flattenJsonLd(p.structuredData ?? p.jsonLd));\n const products = schemas.filter((s) =>\n matchesAnyType(s as Record<string, unknown>, [\n 'Product',\n 'IndividualProduct',\n 'ProductModel',\n ]),\n );\n\n if (products.length === 0) {\n return this.fail(\n 'No Product schema found to check for identifiers.',\n 'Product schema with GTIN/UPC/MPN or SKU.',\n 'None',\n {\n priority: 'high',\n description:\n 'AI agents require unique product identifiers to reliably identify and compare products.',\n code: `{\n \"@context\": \"https://schema.org\",\n \"@type\": \"Product\",\n \"name\": \"Product Name\",\n \"sku\": \"SKU-123456\",\n \"gtin13\": \"1234567890123\"\n}`,\n },\n );\n }\n\n const first = products[0] as Record<string, unknown>;\n // schema.org product identifiers, including productID (valid unique\n // identifier, common in Microdata markup) alongside GTIN/MPN/SKU.\n const identifiers = ['gtin', 'gtin8', 'gtin12', 'gtin13', 'gtin14', 'mpn', 'sku', 'productID'];\n const found = identifiers.filter((id) => first[id]);\n\n if (first['offers']) {\n const offers = Array.isArray(first['offers']) ? first['offers'] : [first['offers']];\n for (const offer of offers) {\n if (offer && typeof offer === 'object') {\n const offerObj = offer as Record<string, unknown>;\n for (const id of identifiers) {\n if (offerObj[id] && !found.includes(id)) {\n found.push(id);\n }\n }\n }\n }\n }\n\n if (found.length > 0) {\n return this.pass(\n `Found product identifiers: ${found.join(', ')}.`,\n 'Product schema with GTIN/UPC/MPN or SKU.',\n found.join(', '),\n );\n }\n\n return this.fail(\n 'No unique product identifiers (GTIN, SKU, MPN) found in Product schema.',\n 'Product schema with GTIN/UPC/MPN or SKU.',\n 'None',\n {\n priority: 'high',\n description:\n 'Unique identifiers are critical for AI agents to precisely match products in global catalogs. Add \"sku\", \"gtin13\", or \"mpn\" to your Product schema.',\n code: `{\n \"@type\": \"Product\",\n \"sku\": \"REQUIRED-ID\",\n \"gtin13\": \"13-DIGIT-GTIN\"\n}`,\n },\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\nimport { flattenJsonLd } from '../../parser';\n\nfunction matchesAnyType(schema: Record<string, unknown>, types: string[]): boolean {\n return types.some((t) => {\n const st = schema['@type'];\n if (typeof st === 'string') return st === t;\n if (Array.isArray(st)) return st.includes(t);\n return false;\n });\n}\n\nexport class ProductDetailsAudit extends Audit {\n static override meta: AuditMeta = {\n id: '3.22',\n category: 'structured-data',\n title: 'Advanced product details',\n failureTitle: 'Advanced product details',\n description:\n 'AI agents use brand, category, and availability status to filter search results and answer availability queries. Missing these details makes your products less likely to surface in filtered AI recommendations.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n applicablePageTypes: ['product'],\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'Missing brand, category, or availability in your Product schema means AI agents cannot filter or surface your products in response to specific shopping queries. Your products are less likely to appear in AI-generated comparisons and \"best of\" recommendations.',\n fix: 'Add brand (as a nested Organization or Brand), category, and availability to your existing Product JSON-LD. If availability lives on your Offer, ensure it uses a schema.org ItemAvailability value.',\n code: `{\n \"@context\": \"https://schema.org\",\n \"@type\": \"Product\",\n \"name\": \"Product Name\",\n \"brand\": {\n \"@type\": \"Brand\",\n \"name\": \"Your Brand\"\n },\n \"category\": \"Electronics > Smartphones\",\n \"offers\": {\n \"@type\": \"Offer\",\n \"availability\": \"https://schema.org/InStock\"\n }\n}`,\n effort: 'easy',\n docsUrl: 'https://schema.org/Product',\n tags: ['json-ld', 'schema', 'product', 'ecommerce'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const schemas = ctx.pages.flatMap((p) => flattenJsonLd(p.structuredData ?? p.jsonLd));\n const products = schemas.filter((s) =>\n matchesAnyType(s as Record<string, unknown>, [\n 'Product',\n 'IndividualProduct',\n 'ProductModel',\n ]),\n );\n\n if (products.length === 0) {\n return this.fail(\n 'No Product schema found.',\n 'Product schema with brand and availability.',\n 'None',\n );\n }\n\n const first = products[0] as Record<string, unknown>;\n const missing: string[] = [];\n\n // 1. Brand or Manufacturer\n const hasBrand = !!first['brand'] || !!first['manufacturer'];\n if (!hasBrand) missing.push('brand');\n\n // 2. Category\n if (!first['category']) missing.push('category');\n\n // 3. Availability (could be in Product or linked Offer)\n let hasAvailability = !!first['availability'];\n if (!hasAvailability && first['offers']) {\n const offers = Array.isArray(first['offers']) ? first['offers'] : [first['offers']];\n hasAvailability = offers.some((o: Record<string, unknown>) => o && o.availability);\n }\n if (!hasAvailability) missing.push('availability');\n\n if (missing.length === 0) {\n return this.pass(\n 'Found brand, category, and availability in Product schema.',\n 'Product schema with brand, category, and availability.',\n 'All present',\n );\n }\n\n if (missing.length < 3) {\n return this.warn(\n `Missing some product details: ${missing.join(', ')}.`,\n 'Product schema with brand, category, and availability.',\n `Missing ${missing.join(', ')}`,\n {\n priority: 'medium',\n description: `AI agents use ${missing.join(', ')} to accurately categorize and recommend your products.`,\n },\n );\n }\n\n return this.fail(\n 'Missing critical product details (brand, category, availability).',\n 'Product schema with brand, category, and availability.',\n 'None',\n {\n priority: 'medium',\n description:\n 'AI agents require brand and availability information to provide accurate shopping advice.',\n },\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\nimport { flattenJsonLd } from '../../parser';\n\nexport class ProductReviewsAudit extends Audit {\n static override meta: AuditMeta = {\n id: '3.23',\n category: 'structured-data',\n title: 'Product reviews and ratings',\n failureTitle: 'Product reviews and ratings',\n description:\n 'AI agents often rank products based on user ratings and review volume. Providing AggregateRating schema allows agents to confidently recommend highly-rated items to users.',\n scoreDisplayMode: 'ternary',\n weight: 0.8,\n applicablePageTypes: ['product'],\n defaultPriority: 'low',\n guidance: {\n impact:\n 'AI agents rank products based on user ratings and review volume. Without AggregateRating schema, agents cannot include your social proof in their recommendations, making your products less competitive in AI-generated \"best of\" lists and comparison answers.',\n fix: 'Add an aggregateRating property to your Product JSON-LD. Include ratingValue, reviewCount, and bestRating to give AI agents full rating context.',\n code: `{\n \"@context\": \"https://schema.org\",\n \"@type\": \"Product\",\n \"name\": \"Product Name\",\n \"aggregateRating\": {\n \"@type\": \"AggregateRating\",\n \"ratingValue\": \"4.8\",\n \"reviewCount\": \"125\",\n \"bestRating\": \"5\"\n }\n}`,\n effort: 'easy',\n docsUrl: 'https://schema.org/AggregateRating',\n tags: ['json-ld', 'schema', 'product', 'ecommerce', 'reviews', 'ratings'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const schemas = ctx.pages.flatMap((p) => flattenJsonLd(p.structuredData ?? p.jsonLd));\n const ratings = schemas.filter((s) => {\n const rec = s as Record<string, unknown>;\n return (\n rec['@type'] === 'AggregateRating' ||\n (rec['aggregateRating'] && typeof rec['aggregateRating'] === 'object')\n );\n });\n\n if (ratings.length > 0) {\n return this.pass(\n 'Found AggregateRating schema.',\n 'AggregateRating schema with ratingValue and reviewCount.',\n 'Found',\n );\n }\n\n return this.warn(\n 'No product ratings found in structured data.',\n 'AggregateRating schema with ratingValue and reviewCount.',\n 'None',\n {\n priority: 'low',\n description:\n 'AI agents use \"AggregateRating\" to include social proof in their recommendations. Consider adding it to your Product pages.',\n code: `{\n \"@type\": \"Product\",\n \"aggregateRating\": {\n \"@type\": \"AggregateRating\",\n \"ratingValue\": \"4.8\",\n \"reviewCount\": \"125\"\n }\n}`,\n },\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class MetaDescriptionAudit extends Audit {\n static override meta: AuditMeta = {\n id: '4.1',\n category: 'meta-tags',\n title: 'Meta description present',\n failureTitle: 'Meta description present',\n description:\n 'AI agents use the meta description as the primary summary of your page when generating answers. Without it, agents must extract a summary from body text, which often produces inaccurate or irrelevant snippets. Add a concise 50-300 character description.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'high',\n guidance: {\n impact:\n 'AI agents use the meta description as the primary summary of your page when generating answers. Without it, agents must extract a summary from body text, which often produces inaccurate or irrelevant snippets.',\n fix: 'Add a <meta name=\"description\"> tag with a concise 50-300 character summary that accurately describes the page content and its value to the reader.',\n code: '<meta name=\"description\" content=\"A concise summary of the page content in 50-300 characters that describes what users will learn.\">',\n effort: 'trivial',\n tags: ['meta-tags', 'seo', 'content-discovery'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const page = ctx.pages[0];\n const desc = page?.meta?.['description'] ?? '';\n const len = desc.length;\n\n if (desc && len >= 50 && len <= 300) {\n return this.pass(\n `Meta description present (${len} chars).`,\n 'meta[description] with 50-300 characters',\n desc,\n page.url,\n );\n }\n\n if (desc && (len < 50 || len > 300)) {\n return this.warn(\n `Meta description length is ${len} chars; should be 50-300.`,\n 'meta[description] with 50-300 characters',\n desc,\n {\n priority: 'high',\n description:\n \"AI agents use the meta description as a primary summary candidate when generating answers about your page. Descriptions outside the 50-300 character range are either too terse for meaningful context or get truncated, reducing your content's chances of being accurately cited.\",\n code: '<meta name=\"description\" content=\"A clear, 50-300 character summary of what this page covers and why it matters.\">',\n },\n page?.url,\n );\n }\n\n return this.fail(\n 'Meta description is missing.',\n 'meta[description] with 50-300 characters',\n 'Not found',\n {\n priority: 'high',\n description:\n 'AI agents use the meta description as the primary summary of your page when generating answers. Without it, agents must extract a summary from body text, which often produces inaccurate or irrelevant snippets. Add a concise 50-300 character description.',\n code: '<meta name=\"description\" content=\"A concise summary of the page content in 50-300 characters.\">',\n },\n page?.url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class MetaAuthorAudit extends Audit {\n static override meta: AuditMeta = {\n id: '4.2',\n category: 'meta-tags',\n title: 'Meta author present',\n failureTitle: 'Meta author present',\n description:\n 'AI agents use the meta author tag to attribute content to a specific person or organization for E-E-A-T scoring. Without it, your content appears authorless, which reduces trust signals in AI ranking systems that prioritize named expertise.',\n scoreDisplayMode: 'binary',\n weight: 1.0,\n applicablePageTypes: ['content'],\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'AI agents use the meta author tag to attribute content to a specific person or organization for E-E-A-T scoring. Without it, your content appears authorless, reducing trust signals in AI ranking systems.',\n fix: 'Add a <meta name=\"author\"> tag with the real name of the content creator or your organization name.',\n code: '<meta name=\"author\" content=\"Jane Smith\">',\n effort: 'trivial',\n tags: ['meta-tags', 'e-e-a-t', 'trust'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const page = ctx.pages[0];\n const author = page?.meta?.['author'] ?? '';\n\n if (author.trim().length > 0) {\n return this.pass(\n `Meta author is set to \"${author}\".`,\n 'meta[author] with a non-empty person or organisation name',\n author,\n page.url,\n );\n }\n\n return this.fail(\n 'Meta author tag is missing or empty.',\n 'meta[author] with a non-empty person or organisation name',\n 'Not found',\n {\n priority: 'medium',\n description:\n 'AI agents use the meta author tag to attribute content to a specific person or organization for E-E-A-T scoring. Without it, your content appears authorless, which reduces trust signals in AI ranking systems that prioritize named expertise.',\n code: '<meta name=\"author\" content=\"Your Name or Organisation\">',\n },\n page?.url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class CanonicalUrlAudit extends Audit {\n static override meta: AuditMeta = {\n id: '4.3',\n category: 'meta-tags',\n title: 'Canonical URL set',\n failureTitle: 'Canonical URL set',\n description:\n 'AI crawlers use canonical URLs to deduplicate content and determine the authoritative version of a page. Without a canonical tag, agents may index multiple URL variants of the same content, diluting your page authority in AI knowledge bases.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'high',\n guidance: {\n impact:\n 'AI crawlers use canonical URLs to deduplicate content and determine the authoritative version of a page. Without a canonical tag, agents may index multiple URL variants, diluting your page authority in AI knowledge bases.',\n fix: 'Add a <link rel=\"canonical\"> tag in <head> with the full absolute URL (starting with https://) of the preferred version of each page.',\n code: '<link rel=\"canonical\" href=\"https://example.com/page\">',\n effort: 'trivial',\n docsUrl:\n 'https://developers.google.com/search/docs/crawling-indexing/consolidate-duplicate-urls',\n tags: ['meta-tags', 'seo', 'deduplication'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const page = ctx.pages[0];\n const canonical = page?.headLinks?.find((l) => l.rel === 'canonical');\n const href = canonical?.href ?? '';\n\n if (href.startsWith('http')) {\n return this.pass(\n `Canonical URL is set to \"${href}\".`,\n '<link rel=\"canonical\"> with an absolute URL starting with http',\n href,\n page.url,\n );\n }\n\n if (href) {\n return this.warn(\n `Canonical URL is present but not absolute: \"${href}\".`,\n '<link rel=\"canonical\"> with an absolute URL starting with http',\n href,\n {\n priority: 'high',\n description:\n 'AI crawlers use canonical URLs to deduplicate content and determine the authoritative version of a page. A relative canonical URL is ambiguous and may cause agents to index duplicate content or miss your preferred URL entirely.',\n code: '<link rel=\"canonical\" href=\"https://example.com/page\">',\n },\n page?.url,\n );\n }\n\n return this.fail(\n 'No canonical URL found.',\n '<link rel=\"canonical\"> with an absolute URL starting with http',\n 'Not found',\n {\n priority: 'high',\n description:\n 'AI crawlers use canonical URLs to deduplicate content and determine the authoritative version of a page. Without a canonical tag, agents may index multiple URL variants of the same content, diluting your page authority in AI knowledge bases.',\n code: '<link rel=\"canonical\" href=\"https://example.com/page\">',\n },\n page?.url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class LanguageAttributeAudit extends Audit {\n static override meta: AuditMeta = {\n id: '4.4',\n category: 'meta-tags',\n title: 'Language attribute',\n failureTitle: 'Language attribute',\n description:\n 'AI agents use the lang attribute to select the correct language model and tokenizer when processing your content. Without it, agents may misinterpret content language, leading to poor translations or incorrect answers in multilingual AI systems.',\n scoreDisplayMode: 'binary',\n weight: 1.0,\n defaultPriority: 'high',\n guidance: {\n impact:\n 'AI agents use the lang attribute to select the correct language model and tokenizer when processing your content. Without it, agents may misinterpret content language, leading to poor translations or incorrect answers in multilingual AI systems.',\n fix: 'Add a lang attribute to the <html> element with the appropriate BCP 47 language code (e.g., \"en\", \"fr\", \"de\", \"ja\").',\n code: '<html lang=\"en\">',\n effort: 'trivial',\n docsUrl: 'https://www.w3.org/International/questions/qa-html-language-declarations',\n tags: ['meta-tags', 'i18n', 'html'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const page = ctx.pages[0];\n const $ = page?.$;\n const lang = $?.('html').attr('lang') ?? '';\n\n if (lang.trim().length > 0) {\n return this.pass(\n `<html lang=\"${lang}\"> is set.`,\n '<html lang=\"...\"> with a non-empty language code',\n lang,\n page.url,\n );\n }\n\n return this.fail(\n 'No lang attribute on <html> element.',\n '<html lang=\"...\"> with a non-empty language code',\n 'Not found',\n {\n priority: 'high',\n description:\n 'AI agents use the lang attribute to select the correct language model and tokenizer when processing your content. Without it, agents may misinterpret content language, leading to poor translations or incorrect answers in multilingual AI systems.',\n code: '<html lang=\"en\">',\n },\n page?.url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class UniqueMetaAudit extends Audit {\n static override meta: AuditMeta = {\n id: '4.5',\n category: 'meta-tags',\n title: 'Unique meta per page',\n failureTitle: 'Unique meta per page',\n description:\n 'AI crawlers use title and description pairs to distinguish between pages. Duplicate meta across pages causes agents to merge or skip content, meaning some of your pages will be invisible in AI-generated answers. Give each page a unique title and description.',\n scoreDisplayMode: 'binary',\n weight: 1.0,\n defaultPriority: 'high',\n guidance: {\n impact:\n 'AI crawlers use title and description pairs to distinguish between pages. Duplicate meta across pages causes agents to merge or skip content, meaning some pages become invisible in AI-generated answers.',\n fix: 'Give each page a unique <title> and <meta name=\"description\"> that specifically describes that page\\'s content. Avoid template descriptions that repeat across pages.',\n code: '<title>Unique Page Title - Your Site</title>\\n<meta name=\"description\" content=\"Unique description for this specific page.\">',\n effort: 'easy',\n tags: ['meta-tags', 'seo', 'deduplication'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n // Group pages by canonical URL so variant query parameters (e.g. ?variant=123) are not counted as duplicate distinct pages\n const canonicalGroups = new Map<string, (typeof ctx.pages)[0]>();\n for (const page of ctx.pages) {\n let canon = (page.meta?.['canonical'] || page.url).trim();\n try {\n const u = new URL(canon);\n u.search = '';\n u.hash = '';\n canon = u.href;\n } catch {\n // ignore\n }\n if (!canonicalGroups.has(canon)) {\n canonicalGroups.set(canon, page);\n }\n }\n\n const uniquePages = Array.from(canonicalGroups.values());\n if (uniquePages.length < 2) {\n return this.pass(\n 'Only one distinct canonical page scanned; uniqueness check not applicable.',\n 'Each page has a unique title + description combination',\n '1 distinct page scanned',\n );\n }\n\n const seen = new Map<string, string>();\n const duplicates: string[] = [];\n\n for (const page of uniquePages) {\n /* v8 ignore next */\n const title = (page.meta?.['title'] ?? page.$?.('title').text() ?? '').trim();\n const desc = (page.meta?.['description'] ?? '').trim();\n const key = `${title}|||${desc}`;\n\n if (seen.has(key)) {\n duplicates.push(`\"${page.url}\" duplicates \"${seen.get(key)}\"`);\n } else {\n seen.set(key, page.url);\n }\n }\n\n if (duplicates.length === 0) {\n return this.pass(\n `All ${uniquePages.length} distinct pages have unique title + description.`,\n 'Each page has a unique title + description combination',\n `${uniquePages.length} unique combinations`,\n );\n }\n\n return this.fail(\n `Duplicate title + description found across pages.`,\n 'Each page has a unique title + description combination',\n duplicates.join('; '),\n {\n priority: 'high',\n description:\n 'AI crawlers use title and description pairs to distinguish between pages. Duplicate meta across pages causes agents to merge or skip content, meaning some of your pages will be invisible in AI-generated answers. Give each page a unique title and description.',\n code: '<title>Unique Page Title</title>\\n<meta name=\"description\" content=\"Unique description for this specific page.\">',\n },\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nconst OG_CORE = ['og:title', 'og:description', 'og:image', 'og:url'] as const;\n\nexport class CoreOpenGraphAudit extends Audit {\n static override meta: AuditMeta = {\n id: '4.6',\n category: 'meta-tags',\n title: 'Core Open Graph tags',\n failureTitle: 'Core Open Graph tags',\n description:\n 'AI agents and social platforms use Open Graph tags to generate rich previews and understand page content at a glance. Missing tags mean agents cannot display proper titles, descriptions, or images when referencing your page in AI-generated responses.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'high',\n guidance: {\n impact:\n 'AI agents and social platforms use Open Graph tags to generate rich previews and understand page content at a glance. Missing tags mean agents cannot display proper titles, descriptions, or images when referencing your page.',\n fix: 'Add all four core OG tags to every page: og:title, og:description, og:image (with an absolute URL), and og:url.',\n code: '<meta property=\"og:title\" content=\"Page Title\">\\n<meta property=\"og:description\" content=\"Page description\">\\n<meta property=\"og:image\" content=\"https://yoursite.com/image.png\">\\n<meta property=\"og:url\" content=\"https://yoursite.com/page\">',\n effort: 'easy',\n docsUrl: 'https://ogp.me/',\n tags: ['meta-tags', 'open-graph', 'social'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const page = ctx.pages[0];\n const present: string[] = [];\n const missing: string[] = [];\n\n for (const tag of OG_CORE) {\n const val = page?.meta?.[tag] ?? '';\n if (val.trim()) {\n present.push(tag);\n } else {\n missing.push(tag);\n }\n }\n\n if (missing.length === 0) {\n return this.pass(\n 'All core OG tags are present and non-empty.',\n 'og:title, og:description, og:image, og:url all present and non-empty',\n present.join(', '),\n page.url,\n );\n }\n\n if (missing.length < OG_CORE.length) {\n return this.warn(\n `Missing OG tags: ${missing.join(', ')}.`,\n 'og:title, og:description, og:image, og:url all present and non-empty',\n /* v8 ignore next */\n present.length > 0 ? `Present: ${present.join(', ')}` : 'None found',\n {\n priority: 'high',\n description: `AI agents and social platforms use Open Graph tags to generate rich previews and understand page content at a glance. Missing tags (${missing.join(', ')}) mean agents cannot display proper titles, descriptions, or images when referencing your page in AI-generated responses.`,\n code: missing.map((t) => `<meta property=\"${t}\" content=\"...\">`).join('\\n'),\n },\n page?.url,\n );\n }\n\n return this.fail(\n `Missing OG tags: ${missing.join(', ')}.`,\n 'og:title, og:description, og:image, og:url all present and non-empty',\n /* v8 ignore next */\n present.length > 0 ? `Present: ${present.join(', ')}` : 'None found',\n {\n priority: 'high',\n description: `AI agents and social platforms use Open Graph tags to generate rich previews and understand page content at a glance. Missing tags (${missing.join(', ')}) mean agents cannot display proper titles, descriptions, or images when referencing your page in AI-generated responses.`,\n code: missing.map((t) => `<meta property=\"${t}\" content=\"...\">`).join('\\n'),\n },\n page?.url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class OgTypeAudit extends Audit {\n static override meta: AuditMeta = {\n id: '4.7',\n category: 'meta-tags',\n title: 'og:type set and appropriate',\n failureTitle: 'og:type set and appropriate',\n description:\n 'AI agents use og:type to classify page content as either a website, article, product, or other entity type. Without it, agents default to treating the page as generic content, missing opportunities for type-specific handling like article freshness scoring.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'AI agents use og:type to classify page content for type-specific handling. Without it, agents treat every page as generic content, missing opportunities for article freshness scoring or product-specific handling.',\n fix: 'Add og:type with the appropriate value: \"article\" for blog posts and articles, \"website\" for homepages and general pages, \"product\" for product pages.',\n code: '<meta property=\"og:type\" content=\"article\">',\n effort: 'trivial',\n docsUrl: 'https://ogp.me/#types',\n tags: ['meta-tags', 'open-graph'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const page = ctx.pages[0];\n const ogType = (page?.meta?.['og:type'] ?? '').trim();\n\n if (!ogType) {\n return this.fail(\n 'og:type is missing.',\n 'og:type present; \"article\" on blog pages, \"website\" on others',\n 'Not found',\n {\n priority: 'medium',\n description:\n 'AI agents use og:type to classify page content as either a website, article, product, or other entity type. Without it, agents default to treating the page as generic content, missing opportunities for type-specific handling like article freshness scoring.',\n code: '<meta property=\"og:type\" content=\"website\">',\n },\n page?.url,\n );\n }\n\n /* v8 ignore next */\n const url = (page?.url ?? '').toLowerCase();\n const isBlogPage = url.includes('/blog') || url.includes('/post') || url.includes('/article');\n\n if (isBlogPage && ogType !== 'article') {\n return this.warn(\n `Blog page has og:type=\"${ogType}\" instead of \"article\".`,\n '\"article\" on blog pages, \"website\" on others',\n ogType,\n {\n priority: 'medium',\n description:\n 'AI agents use og:type \"article\" to apply content-specific handling like freshness scoring and author attribution. Blog pages with og:type \"website\" are treated as static pages instead of time-sensitive content, reducing their prominence in recency-weighted AI answers.',\n code: '<meta property=\"og:type\" content=\"article\">',\n },\n page.url,\n );\n }\n\n return this.pass(\n `og:type is \"${ogType}\".`,\n 'og:type present; \"article\" on blog pages, \"website\" on others',\n ogType,\n page.url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class OgSiteNameAudit extends Audit {\n static override meta: AuditMeta = {\n id: '4.8',\n category: 'meta-tags',\n title: 'og:site_name present',\n failureTitle: 'og:site_name present',\n description:\n 'AI agents use og:site_name to associate individual pages with your brand entity. Without it, agents may not connect pages from your site as belonging to the same organization, fragmenting your brand identity across AI-generated responses.',\n scoreDisplayMode: 'binary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'AI agents use og:site_name to associate individual pages with your brand entity. Without it, agents may not connect pages from your site as belonging to the same organization, fragmenting your brand identity in AI responses.',\n fix: 'Add og:site_name to every page with your consistent brand or site name.',\n code: '<meta property=\"og:site_name\" content=\"Your Site Name\">',\n effort: 'trivial',\n docsUrl: 'https://ogp.me/',\n tags: ['meta-tags', 'open-graph', 'brand'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const page = ctx.pages[0];\n const siteName = (page?.meta?.['og:site_name'] ?? '').trim();\n\n if (siteName) {\n return this.pass(\n `og:site_name is \"${siteName}\".`,\n 'og:site_name present and non-empty',\n siteName,\n page.url,\n );\n }\n\n return this.fail(\n 'og:site_name is missing.',\n 'og:site_name present and non-empty',\n 'Not found',\n {\n priority: 'medium',\n description:\n 'AI agents use og:site_name to associate individual pages with your brand entity. Without it, agents may not connect pages from your site as belonging to the same organization, fragmenting your brand identity across AI-generated responses.',\n code: '<meta property=\"og:site_name\" content=\"Your Site Name\">',\n },\n page?.url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class OgImageAltAudit extends Audit {\n static override meta: AuditMeta = {\n id: '4.9',\n category: 'meta-tags',\n title: 'og:image:alt present',\n failureTitle: 'og:image:alt present',\n description:\n \"AI agents cannot process images directly and rely on og:image:alt text to understand your page's visual content. Without alt text, the OG image is invisible to text-based AI systems that generate answers and summaries about your page.\",\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n \"AI agents cannot process images directly and rely on og:image:alt text to understand your page's visual content. Without alt text, the OG image is invisible to text-based AI systems generating answers about your page.\",\n fix: 'Add an og:image:alt meta tag with a descriptive text that explains what the OG image shows. Keep it concise but informative.',\n code: '<meta property=\"og:image\" content=\"https://yoursite.com/image.png\">\\n<meta property=\"og:image:alt\" content=\"Screenshot of the dashboard showing analytics overview\">',\n effort: 'trivial',\n docsUrl: 'https://ogp.me/',\n tags: ['meta-tags', 'open-graph', 'a11y'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const page = ctx.pages[0];\n const ogImage = (page?.meta?.['og:image'] ?? '').trim();\n const ogImageAlt = (page?.meta?.['og:image:alt'] ?? '').trim();\n\n if (!ogImage) {\n return this.warn(\n 'No og:image found, so og:image:alt is not applicable.',\n 'og:image:alt with descriptive alt text when og:image is set',\n 'No og:image',\n {\n priority: 'medium',\n description:\n 'AI agents cannot process images directly and rely on og:image:alt text to understand visual content. Without an og:image and alt text, agents have no visual context to reference when generating answers about your page.',\n code: '<meta property=\"og:image\" content=\"https://yoursite.com/image.png\">\\n<meta property=\"og:image:alt\" content=\"Description of the image\">',\n },\n page?.url,\n );\n }\n\n if (ogImageAlt) {\n return this.pass(\n `og:image:alt is \"${ogImageAlt}\".`,\n 'og:image:alt with descriptive alt text when og:image is set',\n ogImageAlt,\n page.url,\n );\n }\n\n return this.fail(\n 'og:image is set but og:image:alt is missing.',\n 'og:image:alt with descriptive alt text when og:image is set',\n 'Not found',\n {\n priority: 'medium',\n description:\n \"AI agents cannot process images directly and rely on og:image:alt text to understand your page's visual content. Without alt text, the OG image is invisible to text-based AI systems that generate answers and summaries about your page.\",\n code: '<meta property=\"og:image:alt\" content=\"Description of the image\">',\n },\n page?.url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nconst TWITTER_REQUIRED = ['twitter:card', 'twitter:title', 'twitter:description'] as const;\n\nexport class TwitterCardAudit extends Audit {\n static override meta: AuditMeta = {\n id: '4.10',\n category: 'meta-tags',\n title: 'Twitter Card tags complete',\n failureTitle: 'Twitter Card tags complete',\n description:\n 'AI agents that surface content via social platforms use Twitter Card tags to generate rich previews. Missing tags mean your content appears as a plain URL link with no context, reducing click-through from AI-curated social feeds.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'AI agents that surface content via social platforms use Twitter Card tags to generate rich previews. Missing tags mean your content appears as a plain URL link with no context, reducing click-through from AI-curated social feeds.',\n fix: 'Add all three required Twitter Card meta tags: twitter:card (usually \"summary_large_image\"), twitter:title, and twitter:description.',\n code: '<meta name=\"twitter:card\" content=\"summary_large_image\">\\n<meta name=\"twitter:title\" content=\"Page Title\">\\n<meta name=\"twitter:description\" content=\"Page description\">',\n effort: 'trivial',\n docsUrl: 'https://developer.x.com/en/docs/x-for-websites/cards/overview/abouts-cards',\n tags: ['meta-tags', 'twitter', 'social'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const page = ctx.pages[0];\n const present: string[] = [];\n const missing: string[] = [];\n\n for (const tag of TWITTER_REQUIRED) {\n const val = (page?.meta?.[tag] ?? '').trim();\n if (val) {\n present.push(tag);\n } else {\n missing.push(tag);\n }\n }\n\n if (missing.length === 0) {\n return this.pass(\n 'All required Twitter Card tags are present.',\n 'twitter:card, twitter:title, twitter:description all present',\n present.join(', '),\n page.url,\n );\n }\n\n if (missing.length < TWITTER_REQUIRED.length) {\n return this.warn(\n `Missing Twitter Card tags: ${missing.join(', ')}.`,\n 'twitter:card, twitter:title, twitter:description all present',\n /* v8 ignore next */\n present.length > 0 ? `Present: ${present.join(', ')}` : 'None found',\n {\n priority: 'medium',\n description: `AI agents that surface content via social platforms use Twitter Card tags to generate rich previews. Missing tags (${missing.join(', ')}) mean your content appears as a plain URL link with no context, reducing click-through from AI-curated social feeds.`,\n code: missing.map((t) => `<meta name=\"${t}\" content=\"...\">`).join('\\n'),\n },\n page?.url,\n );\n }\n\n return this.fail(\n `Missing Twitter Card tags: ${missing.join(', ')}.`,\n 'twitter:card, twitter:title, twitter:description all present',\n /* v8 ignore next */\n present.length > 0 ? `Present: ${present.join(', ')}` : 'None found',\n {\n priority: 'medium',\n description: `AI agents that surface content via social platforms use Twitter Card tags to generate rich previews. Missing tags (${missing.join(', ')}) mean your content appears as a plain URL link with no context, reducing click-through from AI-curated social feeds.`,\n code: missing.map((t) => `<meta name=\"${t}\" content=\"...\">`).join('\\n'),\n },\n page?.url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class LlmsTxtLinkAudit extends Audit {\n static override meta: AuditMeta = {\n id: '4.11',\n category: 'meta-tags',\n title: 'llms.txt link in head',\n failureTitle: 'llms.txt link in head',\n description:\n 'The llms.txt link in <head> is how AI agents discover your LLM-friendly content manifest. Without this link tag, agents must guess that /llms.txt exists or rely on well-known URL conventions. An explicit link ensures every AI crawler that visits your page can immediately find your structured content.',\n scoreDisplayMode: 'binary',\n weight: 1.0,\n defaultPriority: 'high',\n guidance: {\n impact:\n 'The llms.txt link in <head> is how AI agents discover your LLM-friendly content manifest. Without it, agents must guess that /llms.txt exists or rely on well-known URL conventions, meaning many AI crawlers will never find your structured content.',\n fix: 'Add a <link rel=\"alternate\"> tag in <head> pointing to your llms.txt file with type=\"text/plain\" and a descriptive title.',\n code: '<link rel=\"alternate\" type=\"text/plain\" href=\"/llms.txt\" title=\"LLMs.txt\">',\n effort: 'trivial',\n docsUrl: 'https://llmstxt.org/',\n tags: ['meta-tags', 'llms-txt', 'ai-discovery'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const page = ctx.pages[0];\n /* v8 ignore start */\n const link = page?.headLinks?.find(\n (l) =>\n l.rel === 'alternate' &&\n l.type === 'text/plain' &&\n (l.title ?? '').toLowerCase().includes('llms'),\n );\n /* v8 ignore stop */\n\n if (link) {\n return this.pass(\n `llms.txt link found: \"${link.href}\".`,\n '<link rel=\"alternate\" type=\"text/plain\" title=\"...LLMs...\">',\n `href=\"${link.href}\" title=\"${link.title}\"`,\n page.url,\n );\n }\n\n return this.fail(\n 'No llms.txt link found in <head>.',\n '<link rel=\"alternate\" type=\"text/plain\" title=\"...LLMs...\">',\n 'Not found',\n {\n priority: 'high',\n description:\n 'The llms.txt link in <head> is how AI agents discover your LLM-friendly content manifest. Without this link tag, agents must guess that /llms.txt exists or rely on well-known URL conventions. An explicit link ensures every AI crawler that visits your page can immediately find your structured content.',\n code: '<link rel=\"alternate\" type=\"text/plain\" href=\"/llms.txt\" title=\"LLMs.txt\">',\n },\n page?.url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class LlmsFullTxtLinkAudit extends Audit {\n static override meta: AuditMeta = {\n id: '4.12',\n category: 'meta-tags',\n title: 'llms-full.txt link in head',\n failureTitle: 'llms-full.txt link in head',\n description:\n 'The llms-full.txt file provides AI agents with a comprehensive, unabridged version of your content optimized for ingestion into context windows. Adding this link in <head> lets agents choose between the summary (llms.txt) and full content versions based on their context budget.',\n scoreDisplayMode: 'binary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'The llms-full.txt file provides AI agents with a comprehensive, unabridged version of your content optimized for large context windows. Without it, agents are limited to the summary version, potentially missing important details about your offerings.',\n fix: 'Create a llms-full.txt file with comprehensive content and add a <link rel=\"alternate\"> tag in <head> pointing to it.',\n code: '<link rel=\"alternate\" type=\"text/plain\" href=\"/llms-full.txt\" title=\"LLMs-full.txt\">',\n effort: 'moderate',\n docsUrl: 'https://llmstxt.org/',\n tags: ['meta-tags', 'llms-txt', 'ai-discovery'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const page = ctx.pages[0];\n /* v8 ignore start */\n const link = page?.headLinks?.find(\n (l) =>\n l.rel === 'alternate' &&\n l.type === 'text/plain' &&\n (l.title ?? '').toLowerCase().includes('llms-full'),\n );\n /* v8 ignore stop */\n\n if (link) {\n return this.pass(\n `llms-full.txt link found: \"${link.href}\".`,\n '<link rel=\"alternate\" type=\"text/plain\" title=\"...LLMs-full...\">',\n `href=\"${link.href}\" title=\"${link.title}\"`,\n page.url,\n );\n }\n\n return this.fail(\n 'No llms-full.txt link found in <head>.',\n '<link rel=\"alternate\" type=\"text/plain\" title=\"...LLMs-full...\">',\n 'Not found',\n {\n priority: 'medium',\n description:\n 'The llms-full.txt file provides AI agents with a comprehensive, unabridged version of your content optimized for ingestion into context windows. Adding this link in <head> lets agents choose between the summary (llms.txt) and full content versions based on their context budget.',\n code: '<link rel=\"alternate\" type=\"text/plain\" href=\"/llms-full.txt\" title=\"LLMs-full.txt\">',\n },\n page?.url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class AiContentDeclarationAudit extends Audit {\n static override meta: AuditMeta = {\n id: '4.13',\n category: 'meta-tags',\n title: 'ai-content-declaration meta',\n failureTitle: 'ai-content-declaration meta',\n description:\n 'The ai-content-declaration meta tag is how AI systems discover your llms.txt or AI usage policy. It signals to crawlers like GPTBot and ClaudeBot where to find machine-readable instructions about how to handle your content. Without it, AI systems have no programmatic way to find your content preferences.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'Without an ai-content-declaration meta tag, AI systems like GPTBot and ClaudeBot have no programmatic way to find your content policy or llms.txt file. This means they cannot respect your content preferences automatically.',\n fix: 'Add a <meta name=\"ai-content-declaration\"> tag with a valid URL pointing to your AI content policy or llms.txt file.',\n code: '<meta name=\"ai-content-declaration\" content=\"https://yoursite.com/llms.txt\">',\n effort: 'trivial',\n tags: ['meta-tags', 'ai-policy', 'ai-discovery'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const page = ctx.pages[0];\n const value = (page?.meta?.['ai-content-declaration'] ?? '').trim();\n\n if (value && (value.startsWith('http://') || value.startsWith('https://'))) {\n return this.pass(\n `ai-content-declaration is set to \"${value}\".`,\n 'meta[ai-content-declaration] with a valid URL',\n value,\n page.url,\n );\n }\n\n if (value) {\n return this.warn(\n `ai-content-declaration is present but not a valid URL: \"${value}\".`,\n 'meta[ai-content-declaration] with a valid URL',\n value,\n {\n priority: 'medium',\n description:\n 'The ai-content-declaration meta tag tells AI systems where to find your content policy (e.g., llms.txt, AI usage guidelines). The value must be a valid URL so agents can programmatically fetch and respect your content preferences. Fix the URL to start with http:// or https://.',\n code: '<meta name=\"ai-content-declaration\" content=\"https://yoursite.com/ai-policy\">',\n },\n page?.url,\n );\n }\n\n return this.fail(\n 'No ai-content-declaration meta tag found.',\n 'meta[ai-content-declaration] with a valid URL',\n 'Not found',\n {\n priority: 'medium',\n description:\n 'The ai-content-declaration meta tag is how AI systems discover your llms.txt or AI usage policy. It signals to crawlers like GPTBot and ClaudeBot where to find machine-readable instructions about how to handle your content. Without it, AI systems have no programmatic way to find your content preferences.',\n code: '<meta name=\"ai-content-declaration\" content=\"https://yoursite.com/llms.txt\">',\n },\n page?.url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class AiInstructionsAudit extends Audit {\n static override meta: AuditMeta = {\n id: '4.14',\n category: 'meta-tags',\n title: 'ai-instructions meta',\n failureTitle: 'ai-instructions meta',\n description:\n 'The ai-instructions meta tag gives AI agents a plain-English brief on how to interact with your site and represent your content. It acts like a system prompt for any AI agent visiting your page, telling it your preferred summarization style, content focus, and usage guidelines.',\n scoreDisplayMode: 'binary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'Without ai-instructions, AI agents have no guidance on how to interact with your site or represent your content. They may summarize your pages inaccurately, speculate about features, or miss your preferred content focus.',\n fix: 'Add a <meta name=\"ai-instructions\"> tag with plain-English instructions telling AI agents how to summarize and represent your content.',\n code: '<meta name=\"ai-instructions\" content=\"Summarise this page as a product overview. Focus on features and pricing. Do not speculate about unreleased features.\">',\n effort: 'trivial',\n tags: ['meta-tags', 'ai-policy', 'ai-discovery'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const page = ctx.pages[0];\n const value = (page?.meta?.['ai-instructions'] ?? '').trim();\n\n if (value) {\n return this.pass(\n `ai-instructions meta tag is present.`,\n 'meta[ai-instructions] with non-empty content',\n value.length > 80 ? value.slice(0, 80) + '...' : value,\n page.url,\n );\n }\n\n return this.fail(\n 'No ai-instructions meta tag found.',\n 'meta[ai-instructions] with non-empty content',\n 'Not found',\n {\n priority: 'medium',\n description:\n 'The ai-instructions meta tag gives AI agents a plain-English brief on how to interact with your site and represent your content. It acts like a system prompt for any AI agent visiting your page, telling it your preferred summarization style, content focus, and usage guidelines.',\n code: '<meta name=\"ai-instructions\" content=\"Summarise this page as a product overview. Focus on features and pricing. Do not speculate about unreleased features.\">',\n },\n page?.url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class MarkdownAlternateAudit extends Audit {\n static override meta: AuditMeta = {\n id: '4.15',\n category: 'meta-tags',\n title: 'Markdown alternate link',\n failureTitle: 'Markdown alternate link',\n description:\n 'AI agents prefer Markdown over HTML because it strips away layout noise and fits more content into limited context windows. A Markdown alternate link lets agents fetch a clean, token-efficient version of your page, improving the accuracy of AI-generated summaries.',\n scoreDisplayMode: 'binary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'AI agents prefer Markdown over HTML because it strips away layout noise and fits more content into limited context windows. Without a Markdown alternate, agents must parse full HTML, reducing the accuracy of AI-generated summaries.',\n fix: 'Create a Markdown version of your page and add a <link rel=\"alternate\"> tag in <head> with type=\"text/markdown\" pointing to it.',\n code: '<link rel=\"alternate\" type=\"text/markdown\" href=\"/page.md\">',\n effort: 'moderate',\n tags: ['meta-tags', 'markdown', 'ai-discovery'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const page = ctx.pages[0];\n const link = page?.headLinks?.find((l) => l.rel === 'alternate' && l.type === 'text/markdown');\n\n if (link) {\n return this.pass(\n `Markdown alternate link found: \"${link.href}\".`,\n '<link rel=\"alternate\" type=\"text/markdown\">',\n `href=\"${link.href}\"`,\n page.url,\n );\n }\n\n return this.fail(\n 'No Markdown alternate link found in <head>.',\n '<link rel=\"alternate\" type=\"text/markdown\">',\n 'Not found',\n {\n priority: 'medium',\n description:\n 'AI agents prefer Markdown over HTML because it strips away layout noise and fits more content into limited context windows. A Markdown alternate link lets agents fetch a clean, token-efficient version of your page, improving the accuracy of AI-generated summaries.',\n code: '<link rel=\"alternate\" type=\"text/markdown\" href=\"/page.md\">',\n },\n page?.url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class RssFeedLinkAudit extends Audit {\n static override meta: AuditMeta = {\n id: '4.16',\n category: 'meta-tags',\n title: 'RSS feed link in head',\n failureTitle: 'RSS feed link in head',\n description:\n 'AI agents use RSS feeds to efficiently monitor your site for new content without re-crawling every page. Without an RSS link, agents must perform expensive full-site crawls to detect updates, meaning your new content takes longer to appear in AI-generated answers.',\n scoreDisplayMode: 'binary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'AI agents use RSS feeds to efficiently monitor your site for new content without re-crawling every page. Without an RSS link, your new content takes longer to appear in AI-generated answers because agents must perform expensive full-site crawls.',\n fix: 'Create an RSS feed for your content and add a <link rel=\"alternate\"> tag in <head> with type=\"application/rss+xml\".',\n code: '<link rel=\"alternate\" type=\"application/rss+xml\" href=\"/feed.xml\" title=\"RSS Feed\">',\n effort: 'easy',\n tags: ['meta-tags', 'rss', 'content-discovery'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const page = ctx.pages[0];\n const link = page?.headLinks?.find(\n (l) => l.rel === 'alternate' && l.type === 'application/rss+xml',\n );\n\n if (link) {\n return this.pass(\n `RSS feed link found: \"${link.href}\".`,\n '<link rel=\"alternate\" type=\"application/rss+xml\">',\n `href=\"${link.href}\"`,\n page.url,\n );\n }\n\n return this.fail(\n 'No RSS feed link found in <head>.',\n '<link rel=\"alternate\" type=\"application/rss+xml\">',\n 'Not found',\n {\n priority: 'medium',\n description:\n 'AI agents use RSS feeds to efficiently monitor your site for new content without re-crawling every page. Without an RSS link, agents must perform expensive full-site crawls to detect updates, meaning your new content takes longer to appear in AI-generated answers.',\n code: '<link rel=\"alternate\" type=\"application/rss+xml\" href=\"/feed.xml\" title=\"RSS Feed\">',\n },\n page?.url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class McpDiscoveryLinkAudit extends Audit {\n static override meta: AuditMeta = {\n id: '4.17',\n category: 'meta-tags',\n title: 'MCP discovery link in head',\n failureTitle: 'MCP discovery link in head',\n description:\n \"The MCP (Model Context Protocol) discovery link in <head> enables AI agents like Claude and ChatGPT to find and connect to your site's tool endpoints. This is how agents discover that your site offers programmatic actions (search, booking, data queries) beyond static content. Without it, agents cannot discover your MCP server.\",\n scoreDisplayMode: 'binary',\n weight: 1.0,\n defaultPriority: 'low',\n guidance: {\n impact:\n \"Without an MCP discovery link, AI agents like Claude and ChatGPT cannot find your site's tool endpoints. This means agents cannot discover that your site offers programmatic actions (search, booking, data queries) beyond static content.\",\n fix: 'If your site offers API endpoints or tools, create an MCP server configuration and add a <link rel=\"alternate\"> tag in <head> pointing to it.',\n code: '<link rel=\"alternate\" type=\"application/json\" href=\"/mcp.json\" title=\"MCP Server\">',\n effort: 'complex',\n docsUrl: 'https://modelcontextprotocol.io/',\n tags: ['meta-tags', 'mcp', 'agentic-commerce', 'ai-discovery'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const page = ctx.pages[0];\n const link = page?.headLinks?.find(\n (l) =>\n (l.rel === 'alternate' &&\n l.type === 'application/json' &&\n (l.title ?? '').toLowerCase().includes('mcp')) ||\n l.rel === 'mcp-discovery' ||\n (l.rel === 'alternate' && (l.href ?? '').toLowerCase().includes('mcp.json')),\n );\n\n if (link) {\n return this.pass(\n `MCP discovery link found: \"${link.href}\".`,\n '<link rel=\"alternate\" type=\"application/json\" title=\"...MCP...\">',\n `href=\"${link.href}\" title=\"${link.title}\"`,\n page.url,\n );\n }\n\n return this.fail(\n 'No MCP discovery link found in <head>.',\n '<link rel=\"alternate\" type=\"application/json\" title=\"...MCP...\">',\n 'Not found',\n {\n priority: 'low',\n description:\n \"The MCP (Model Context Protocol) discovery link in <head> enables AI agents like Claude and ChatGPT to find and connect to your site's tool endpoints. This is how agents discover that your site offers programmatic actions (search, booking, data queries) beyond static content. Without it, agents cannot discover your MCP server.\",\n code: '<link rel=\"alternate\" type=\"application/json\" href=\"/mcp.json\" title=\"MCP Server\">',\n },\n page?.url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class OpenApiLinkAudit extends Audit {\n static override meta: AuditMeta = {\n id: '4.18',\n category: 'meta-tags',\n title: 'OpenAPI spec link in head',\n failureTitle: 'OpenAPI spec link in head',\n description:\n 'AI agents use OpenAPI specifications to understand your API endpoints, parameters, and response formats. An OpenAPI link in <head> enables agents to programmatically interact with your API without manual documentation parsing, powering agentic workflows that call your services.',\n scoreDisplayMode: 'binary',\n weight: 1.0,\n defaultPriority: 'low',\n guidance: {\n impact:\n 'Without an OpenAPI spec link, AI agents cannot programmatically understand your API endpoints, parameters, and response formats. This blocks agentic workflows that could call your API services on behalf of users.',\n fix: 'If your site has an API, create an OpenAPI specification and add a <link rel=\"alternate\"> tag in <head> pointing to it.',\n code: '<link rel=\"alternate\" type=\"application/json\" href=\"/openapi.json\" title=\"OpenAPI Spec\">',\n effort: 'complex',\n docsUrl: 'https://swagger.io/specification/',\n tags: ['meta-tags', 'openapi', 'api', 'ai-discovery'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const page = ctx.pages[0];\n /* v8 ignore start */\n const link = page?.headLinks?.find(\n (l) =>\n l.rel === 'alternate' &&\n l.type === 'application/json' &&\n (l.title ?? '').toLowerCase().includes('openapi'),\n );\n /* v8 ignore stop */\n\n if (link) {\n return this.pass(\n `OpenAPI spec link found: \"${link.href}\".`,\n '<link rel=\"alternate\" type=\"application/json\" title=\"...OpenAPI...\">',\n `href=\"${link.href}\" title=\"${link.title}\"`,\n page.url,\n );\n }\n\n return this.fail(\n 'No OpenAPI spec link found in <head>.',\n '<link rel=\"alternate\" type=\"application/json\" title=\"...OpenAPI...\">',\n 'Not found',\n {\n priority: 'low',\n description:\n 'AI agents use OpenAPI specifications to understand your API endpoints, parameters, and response formats. An OpenAPI link in <head> enables agents to programmatically interact with your API without manual documentation parsing, powering agentic workflows that call your services.',\n code: '<link rel=\"alternate\" type=\"application/json\" href=\"/openapi.json\" title=\"OpenAPI Spec\">',\n },\n page?.url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class AiCatalogLinkAudit extends Audit {\n static override meta: AuditMeta = {\n id: '4.19',\n category: 'meta-tags',\n title: 'AI Catalog link in head',\n failureTitle: 'AI Catalog link in head',\n description:\n 'The AI Catalog provides a structured manifest of all AI-consumable resources on your site (APIs, datasets, tools). An AI Catalog link in <head> lets agents discover your full range of machine-readable content in a single request instead of crawling your entire site.',\n scoreDisplayMode: 'binary',\n weight: 1.0,\n defaultPriority: 'low',\n guidance: {\n impact:\n 'Without an AI Catalog link, agents must crawl your entire site to discover AI-consumable resources (APIs, datasets, tools). The catalog lets them find everything in a single request, dramatically improving discovery efficiency.',\n fix: 'Create an AI Catalog JSON file listing your AI-consumable resources and add a <link rel=\"alternate\"> tag in <head> pointing to it.',\n code: '<link rel=\"alternate\" type=\"application/json\" href=\"/ai-catalog.json\" title=\"AI Catalog\">',\n effort: 'moderate',\n tags: ['meta-tags', 'ai-catalog', 'ai-discovery'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const page = ctx.pages[0];\n /* v8 ignore start */\n const link = page?.headLinks?.find(\n (l) =>\n l.rel === 'alternate' &&\n l.type === 'application/json' &&\n (l.title ?? '').toLowerCase().includes('ai catalog'),\n );\n /* v8 ignore stop */\n\n if (link) {\n return this.pass(\n `AI Catalog link found: \"${link.href}\".`,\n '<link rel=\"alternate\" type=\"application/json\" title=\"...AI Catalog...\">',\n `href=\"${link.href}\" title=\"${link.title}\"`,\n page.url,\n );\n }\n\n return this.fail(\n 'No AI Catalog link found in <head>.',\n '<link rel=\"alternate\" type=\"application/json\" title=\"...AI Catalog...\">',\n 'Not found',\n {\n priority: 'low',\n description:\n 'The AI Catalog provides a structured manifest of all AI-consumable resources on your site (APIs, datasets, tools). An AI Catalog link in <head> lets agents discover your full range of machine-readable content in a single request instead of crawling your entire site.',\n code: '<link rel=\"alternate\" type=\"application/json\" href=\"/ai-catalog.json\" title=\"AI Catalog\">',\n },\n page?.url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class MetaRobotsAudit extends Audit {\n static override meta: AuditMeta = {\n id: '4.20',\n category: 'meta-tags',\n title: 'meta robots not blocking',\n failureTitle: 'meta robots not blocking',\n description:\n 'The \"noindex\" directive tells AI crawlers like GPTBot and ClaudeBot to skip this page entirely. Your content will be invisible to AI answer engines and will never appear in AI-generated responses. Remove \"noindex\" unless you intentionally want to block AI indexing.',\n scoreDisplayMode: 'binary',\n weight: 1.0,\n defaultPriority: 'critical',\n guidance: {\n impact:\n 'The \"noindex\" directive tells AI crawlers like GPTBot and ClaudeBot to skip this page entirely. Your content will be invisible to AI answer engines and will never appear in AI-generated responses.',\n fix: 'Remove the \"noindex\" directive from the meta robots tag. Replace with \"index, follow\" or remove the tag entirely to allow AI indexing.',\n code: '<meta name=\"robots\" content=\"index, follow\">',\n effort: 'trivial',\n tags: ['meta-tags', 'indexing', 'critical'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const page = ctx.pages[0];\n const robots = (page?.meta?.['robots'] ?? '').trim().toLowerCase();\n\n if (!robots) {\n return this.pass(\n 'No meta robots tag found (not blocking by default).',\n 'meta[robots] absent or does not contain \"noindex\"',\n 'Not present',\n page?.url,\n );\n }\n\n if (robots.includes('noindex')) {\n return this.fail(\n `meta robots contains \"noindex\": \"${robots}\".`,\n 'meta[robots] does not contain \"noindex\"',\n robots,\n {\n priority: 'critical',\n description:\n 'The \"noindex\" directive tells AI crawlers like GPTBot and ClaudeBot to skip this page entirely. Your content will be invisible to AI answer engines and will never appear in AI-generated responses. Remove \"noindex\" unless you intentionally want to block AI indexing.',\n code: '<meta name=\"robots\" content=\"index, follow\">',\n },\n page?.url,\n );\n }\n\n return this.pass(\n `meta robots is \"${robots}\" (no blocking directives).`,\n 'meta[robots] does not contain \"noindex\"',\n robots,\n page.url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nfunction tryParseJson(body: string): unknown {\n try {\n return JSON.parse(body);\n } catch {\n return undefined;\n }\n}\n\nfunction isObject(val: unknown): val is Record<string, unknown> {\n return typeof val === 'object' && val !== null && !Array.isArray(val);\n}\n\nexport class OpenApiExistsAudit extends Audit {\n static override meta: AuditMeta = {\n id: '5.1',\n category: 'agent-tools',\n title: 'OpenAPI spec exists',\n failureTitle: 'OpenAPI spec exists',\n description:\n 'Without an OpenAPI spec, AI agents can only read your site but cannot take actions like submitting forms, searching, or booking demos. An OpenAPI spec turns your site from a passive document into an interactive tool that agents can use on behalf of users.',\n scoreDisplayMode: 'binary',\n weight: 1.0,\n defaultPriority: 'high',\n guidance: {\n impact:\n 'Without an OpenAPI spec, AI agents can only read your pages but cannot take actions like submitting forms, searching content, or booking demos. Your site is invisible as an interactive tool, and agents will direct users to competitors who expose APIs.',\n fix: \"Create an /openapi.json file (OpenAPI 3.0+) describing your site's API endpoints. Start with your most important interactions: contact forms, search, and product lookups.\",\n code: `// /openapi.json\n{\n \"openapi\": \"3.0.3\",\n \"info\": {\n \"title\": \"Your Site API\",\n \"version\": \"1.0.0\",\n \"x-ai-instructions\": \"Use this API to interact with Your Site.\"\n },\n \"servers\": [{ \"url\": \"https://yoursite.com/api\" }],\n \"paths\": {\n \"/contact\": {\n \"post\": {\n \"operationId\": \"submitContact\",\n \"summary\": \"Submit a contact inquiry\",\n \"requestBody\": {\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"type\": \"object\",\n \"properties\": {\n \"name\": { \"type\": \"string\" },\n \"email\": { \"type\": \"string\" },\n \"message\": { \"type\": \"string\" }\n }\n }\n }\n }\n },\n \"responses\": { \"200\": { \"description\": \"Success\" } }\n }\n }\n }\n}`,\n effort: 'moderate',\n docsUrl: 'https://swagger.io/specification/',\n tags: ['openapi', 'api', 'discovery'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const jsonResult = ctx.rootFiles['/openapi.json'];\n const yamlResult = ctx.rootFiles['/openapi.yaml'];\n\n // Try JSON first\n if (jsonResult && jsonResult.status === 200 && jsonResult.body) {\n const parsed = tryParseJson(jsonResult.body);\n if (isObject(parsed)) {\n return this.pass(\n 'Valid OpenAPI JSON spec found at /openapi.json.',\n '/openapi.json or /openapi.yaml returns 200 with valid content',\n 'Valid JSON at /openapi.json',\n );\n }\n }\n\n // Try YAML\n if (yamlResult && yamlResult.status === 200 && yamlResult.body) {\n if (yamlResult.body.includes('openapi:')) {\n return this.pass(\n 'OpenAPI YAML spec found at /openapi.yaml.',\n '/openapi.json or /openapi.yaml returns 200 with valid content',\n 'YAML with openapi: directive at /openapi.yaml',\n );\n }\n }\n\n return this.fail(\n 'No valid OpenAPI spec found at /openapi.json or /openapi.yaml.',\n '/openapi.json or /openapi.yaml returns 200 with valid content',\n 'No valid OpenAPI spec detected',\n {\n priority: 'high',\n description:\n 'Without an OpenAPI spec, AI agents can only read your site but cannot take actions like submitting forms, searching, or booking demos. An OpenAPI spec turns your site from a passive document into an interactive tool that agents can use on behalf of users.',\n code: `// /openapi.json\\n{\\n \"openapi\": \"3.0.3\",\\n \"info\": {\\n \"title\": \"Your Site API\",\\n \"version\": \"1.0.0\",\\n \"x-ai-instructions\": \"Use this API to interact with Your Site.\"\\n },\\n \"servers\": [{ \"url\": \"https://yoursite.com/api\" }],\\n \"paths\": {\\n \"/contact\": {\\n \"post\": {\\n \"operationId\": \"submitContact\",\\n \"summary\": \"Submit a contact inquiry\",\\n \"requestBody\": {\\n \"content\": {\\n \"application/json\": {\\n \"schema\": {\\n \"type\": \"object\",\\n \"properties\": {\\n \"name\": { \"type\": \"string\" },\\n \"email\": { \"type\": \"string\" },\\n \"message\": { \"type\": \"string\" }\\n }\\n }\\n }\\n }\\n },\\n \"responses\": { \"200\": { \"description\": \"Success\" } }\\n }\\n }\\n }\\n}`,\n },\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nfunction tryParseJson(body: string): unknown {\n try {\n return JSON.parse(body);\n } catch {\n return undefined;\n }\n}\n\nfunction isObject(val: unknown): val is Record<string, unknown> {\n return typeof val === 'object' && val !== null && !Array.isArray(val);\n}\n\ntype OpenApiPaths = Record<string, Record<string, unknown>>;\ntype OpenApiOperation = Record<string, unknown>;\n\nconst HTTP_METHODS = ['get', 'post', 'put', 'patch', 'delete', 'options', 'head', 'trace'];\n\nfunction getOpenApiSpec(ctx: {\n rootFiles: Record<string, { status: number; body: string }>;\n}): Record<string, unknown> | undefined {\n const jsonResult = ctx.rootFiles['/openapi.json'];\n if (jsonResult && jsonResult.status === 200 && jsonResult.body) {\n const parsed = tryParseJson(jsonResult.body);\n if (isObject(parsed)) return parsed;\n }\n return undefined;\n}\n\nfunction getOperations(\n spec: Record<string, unknown>,\n): Array<{ path: string; method: string; op: OpenApiOperation }> {\n const paths = spec['paths'] as OpenApiPaths | undefined;\n if (!isObject(paths)) return [];\n\n const ops: Array<{ path: string; method: string; op: OpenApiOperation }> = [];\n for (const [path, pathItem] of Object.entries(paths)) {\n if (!isObject(pathItem)) continue;\n for (const method of HTTP_METHODS) {\n const op = pathItem[method];\n if (isObject(op)) {\n ops.push({ path, method, op: op as OpenApiOperation });\n }\n }\n }\n return ops;\n}\n\nexport class OpenApiEndpointsAudit extends Audit {\n static override meta: AuditMeta = {\n id: '5.2',\n category: 'agent-tools',\n title: 'OpenAPI has endpoints',\n failureTitle: 'OpenAPI has endpoints',\n description:\n 'An OpenAPI spec without endpoints is like a menu with no items. AI agents need at least one path with an operation to know what actions they can perform on your site. Add your most important endpoints first.',\n scoreDisplayMode: 'binary',\n weight: 1.0,\n defaultPriority: 'high',\n guidance: {\n impact:\n 'An OpenAPI spec without endpoints is unusable -- AI agents see a spec file but have zero actions they can perform. Your site remains a passive document that agents cannot interact with programmatically.',\n fix: 'Add at least one path with an HTTP operation (GET, POST, etc.) to your OpenAPI spec. Start with your most valuable endpoints: search, contact, or product lookup.',\n code: `\"paths\": {\n \"/search\": {\n \"get\": {\n \"operationId\": \"searchContent\",\n \"summary\": \"Search site content\",\n \"parameters\": [{\n \"name\": \"q\", \"in\": \"query\", \"schema\": { \"type\": \"string\" }\n }],\n \"responses\": { \"200\": { \"description\": \"Search results\" } }\n }\n }\n}`,\n effort: 'moderate',\n docsUrl: 'https://swagger.io/specification/#paths-object',\n tags: ['openapi', 'endpoints', 'api'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const spec = getOpenApiSpec(ctx);\n if (!spec) {\n return this.fail(\n 'No parseable OpenAPI JSON spec found.',\n 'At least one path with one operation in the OpenAPI spec',\n 'No spec',\n {\n priority: 'high',\n description: OpenApiEndpointsAudit.meta.description,\n code: `\"paths\": {\\n \"/search\": {\\n \"get\": {\\n \"operationId\": \"searchContent\",\\n \"summary\": \"Search site content\",\\n \"parameters\": [{\\n \"name\": \"q\", \"in\": \"query\", \"schema\": { \"type\": \"string\" }\\n }],\\n \"responses\": { \"200\": { \"description\": \"Search results\" } }\\n }\\n }\\n}`,\n },\n );\n }\n\n const ops = getOperations(spec);\n if (ops.length > 0) {\n return this.pass(\n `OpenAPI spec defines ${ops.length} operation(s) across its paths.`,\n 'At least one path with one operation in the OpenAPI spec',\n `${ops.length} operation(s)`,\n );\n }\n\n return this.fail(\n 'OpenAPI spec has no operations defined in paths.',\n 'At least one path with one operation in the OpenAPI spec',\n '0 operations',\n {\n priority: 'high',\n description: OpenApiEndpointsAudit.meta.description,\n code: `\"paths\": {\\n \"/search\": {\\n \"get\": {\\n \"operationId\": \"searchContent\",\\n \"summary\": \"Search site content\",\\n \"parameters\": [{\\n \"name\": \"q\", \"in\": \"query\", \"schema\": { \"type\": \"string\" }\\n }],\\n \"responses\": { \"200\": { \"description\": \"Search results\" } }\\n }\\n }\\n}`,\n },\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nfunction tryParseJson(body: string): unknown {\n try {\n return JSON.parse(body);\n } catch {\n return undefined;\n }\n}\n\nfunction isObject(val: unknown): val is Record<string, unknown> {\n return typeof val === 'object' && val !== null && !Array.isArray(val);\n}\n\ntype OpenApiPaths = Record<string, Record<string, unknown>>;\ntype OpenApiOperation = Record<string, unknown>;\n\nconst HTTP_METHODS = ['get', 'post', 'put', 'patch', 'delete', 'options', 'head', 'trace'];\n\nfunction getOpenApiSpec(ctx: {\n rootFiles: Record<string, { status: number; body: string }>;\n}): Record<string, unknown> | undefined {\n const jsonResult = ctx.rootFiles['/openapi.json'];\n if (jsonResult && jsonResult.status === 200 && jsonResult.body) {\n const parsed = tryParseJson(jsonResult.body);\n if (isObject(parsed)) return parsed;\n }\n return undefined;\n}\n\nfunction getOperations(\n spec: Record<string, unknown>,\n): Array<{ path: string; method: string; op: OpenApiOperation }> {\n const paths = spec['paths'] as OpenApiPaths | undefined;\n if (!isObject(paths)) return [];\n\n const ops: Array<{ path: string; method: string; op: OpenApiOperation }> = [];\n for (const [path, pathItem] of Object.entries(paths)) {\n if (!isObject(pathItem)) continue;\n for (const method of HTTP_METHODS) {\n const op = pathItem[method];\n if (isObject(op)) {\n ops.push({ path, method, op: op as OpenApiOperation });\n }\n }\n }\n return ops;\n}\n\nexport class OpenApiOperationIdsAudit extends Audit {\n static override meta: AuditMeta = {\n id: '5.3',\n category: 'agent-tools',\n title: 'OpenAPI has operationIds',\n failureTitle: 'OpenAPI has operationIds',\n description:\n 'AI agents use operationIds as stable function names when calling your API. Without unique operationIds, agents must guess endpoint names from paths, leading to ambiguity and errors. Use descriptive camelCase names.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'AI agents use operationIds as stable function names when calling your API. Without unique operationIds, agents must infer endpoint names from URL paths, leading to ambiguous calls, naming collisions, and broken integrations.',\n fix: 'Add a unique, descriptive operationId (camelCase) to every operation in your OpenAPI spec. Use verb-noun format like \"searchContent\", \"submitContactForm\", or \"getProductDetails\".',\n code: `\"paths\": {\n \"/contact\": {\n \"post\": {\n \"operationId\": \"submitContactForm\",\n \"summary\": \"Submit a contact inquiry\"\n }\n },\n \"/search\": {\n \"get\": {\n \"operationId\": \"searchContent\",\n \"summary\": \"Search site content\"\n }\n }\n}`,\n effort: 'easy',\n docsUrl: 'https://swagger.io/specification/#operation-object',\n tags: ['openapi', 'operation-ids', 'api'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const spec = getOpenApiSpec(ctx);\n if (!spec) {\n return this.fail(\n 'No parseable OpenAPI JSON spec found.',\n 'Every operation has a unique operationId',\n 'No spec',\n {\n priority: 'medium',\n description: OpenApiOperationIdsAudit.meta.description,\n code: `\"paths\": {\\n \"/contact\": {\\n \"post\": {\\n \"operationId\": \"submitContactForm\",\\n \"summary\": \"Submit a contact inquiry\"\\n }\\n },\\n \"/search\": {\\n \"get\": {\\n \"operationId\": \"searchContent\",\\n \"summary\": \"Search site content\"\\n }\\n }\\n}`,\n },\n );\n }\n\n const ops = getOperations(spec);\n if (ops.length === 0) {\n return this.fail(\n 'No operations to check.',\n 'Every operation has a unique operationId',\n '0 operations',\n {\n priority: 'medium',\n description: OpenApiOperationIdsAudit.meta.description,\n code: `\"paths\": {\\n \"/contact\": {\\n \"post\": {\\n \"operationId\": \"submitContactForm\",\\n \"summary\": \"Submit a contact inquiry\"\\n }\\n },\\n \"/search\": {\\n \"get\": {\\n \"operationId\": \"searchContent\",\\n \"summary\": \"Search site content\"\\n }\\n }\\n}`,\n },\n );\n }\n\n const ids = new Set<string>();\n let missing = 0;\n let duplicates = 0;\n\n for (const { op } of ops) {\n const id = op['operationId'];\n if (typeof id !== 'string' || !id) {\n missing++;\n } else if (ids.has(id)) {\n duplicates++;\n } else {\n ids.add(id);\n }\n }\n\n if (missing === 0 && duplicates === 0) {\n return this.pass(\n `All ${ops.length} operation(s) have unique operationIds.`,\n 'Every operation has a unique operationId',\n `${ops.length} unique operationId(s)`,\n );\n }\n\n const issues: string[] = [];\n if (missing > 0) issues.push(`${missing} missing`);\n if (duplicates > 0) issues.push(`${duplicates} duplicate(s)`);\n\n return this.warn(\n `operationId issues: ${issues.join(', ')} out of ${ops.length} operation(s).`,\n 'Every operation has a unique operationId',\n issues.join(', '),\n {\n priority: 'medium',\n description: OpenApiOperationIdsAudit.meta.description,\n code: `\"paths\": {\\n \"/contact\": {\\n \"post\": {\\n \"operationId\": \"submitContactForm\",\\n \"summary\": \"Submit a contact inquiry\"\\n }\\n },\\n \"/search\": {\\n \"get\": {\\n \"operationId\": \"searchContent\",\\n \"summary\": \"Search site content\"\\n }\\n }\\n}`,\n },\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nfunction tryParseJson(body: string): unknown {\n try {\n return JSON.parse(body);\n } catch {\n return undefined;\n }\n}\n\nfunction isObject(val: unknown): val is Record<string, unknown> {\n return typeof val === 'object' && val !== null && !Array.isArray(val);\n}\n\nfunction getOpenApiSpec(ctx: {\n rootFiles: Record<string, { status: number; body: string }>;\n}): Record<string, unknown> | undefined {\n const jsonResult = ctx.rootFiles['/openapi.json'];\n if (jsonResult && jsonResult.status === 200 && jsonResult.body) {\n const parsed = tryParseJson(jsonResult.body);\n if (isObject(parsed)) return parsed;\n }\n return undefined;\n}\n\nexport class OpenApiAiInstructionsAudit extends Audit {\n static override meta: AuditMeta = {\n id: '5.4',\n category: 'agent-tools',\n title: 'x-ai-instructions in OpenAPI',\n failureTitle: 'x-ai-instructions in OpenAPI',\n description:\n 'The x-ai-instructions field lets you give natural-language guidance to AI agents about how to use your API. This is your chance to explain business logic, rate limits, authentication flow, and common use cases in plain English.',\n scoreDisplayMode: 'binary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n \"Without x-ai-instructions, AI agents must infer your API's business logic, usage patterns, and constraints from endpoint names alone. This leads to incorrect API usage, violated rate limits, and poor user experiences.\",\n fix: 'Add an x-ai-instructions string to the info object of your OpenAPI spec. Describe common workflows, rate limits, authentication requirements, and any sequencing constraints in plain English.',\n code: `\"info\": {\n \"title\": \"Your Site API\",\n \"version\": \"1.0.0\",\n \"x-ai-instructions\": \"This API lets you search content, submit contact forms, and retrieve product details. Always call searchContent before submitContact. Rate limit: 10 requests/minute. No authentication required for read endpoints.\"\n}`,\n effort: 'trivial',\n tags: ['openapi', 'ai-instructions', 'api'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const spec = getOpenApiSpec(ctx);\n if (!spec) {\n return this.fail(\n 'No parseable OpenAPI JSON spec found.',\n 'info object has x-ai-instructions field',\n 'No spec',\n {\n priority: 'medium',\n description: OpenApiAiInstructionsAudit.meta.description,\n code: `\"info\": {\\n \"title\": \"Your Site API\",\\n \"version\": \"1.0.0\",\\n \"x-ai-instructions\": \"This API lets you search content, submit contact forms, and retrieve product details. Always call searchContent before submitContact. Rate limit: 10 requests/minute. No authentication required for read endpoints.\"\\n}`,\n },\n );\n }\n\n const info = spec['info'];\n if (\n isObject(info) &&\n typeof info['x-ai-instructions'] === 'string' &&\n info['x-ai-instructions']\n ) {\n return this.pass(\n 'OpenAPI info object contains x-ai-instructions.',\n 'info object has x-ai-instructions field',\n 'x-ai-instructions present',\n );\n }\n\n return this.fail(\n 'OpenAPI info object does not contain x-ai-instructions.',\n 'info object has x-ai-instructions field',\n 'x-ai-instructions missing',\n {\n priority: 'medium',\n description: OpenApiAiInstructionsAudit.meta.description,\n code: `\"info\": {\\n \"title\": \"Your Site API\",\\n \"version\": \"1.0.0\",\\n \"x-ai-instructions\": \"This API lets you search content, submit contact forms, and retrieve product details. Always call searchContent before submitContact. Rate limit: 10 requests/minute. No authentication required for read endpoints.\"\\n}`,\n },\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nfunction tryParseJson(body: string): unknown {\n try {\n return JSON.parse(body);\n } catch {\n return undefined;\n }\n}\n\nfunction isObject(val: unknown): val is Record<string, unknown> {\n return typeof val === 'object' && val !== null && !Array.isArray(val);\n}\n\nfunction getOpenApiSpec(ctx: {\n rootFiles: Record<string, { status: number; body: string }>;\n}): Record<string, unknown> | undefined {\n const jsonResult = ctx.rootFiles['/openapi.json'];\n if (jsonResult && jsonResult.status === 200 && jsonResult.body) {\n const parsed = tryParseJson(jsonResult.body);\n if (isObject(parsed)) return parsed;\n }\n return undefined;\n}\n\nexport class OpenApiServersAudit extends Audit {\n static override meta: AuditMeta = {\n id: '5.5',\n category: 'agent-tools',\n title: 'OpenAPI servers array valid',\n failureTitle: 'OpenAPI servers array valid',\n description:\n 'Without a servers array, AI agents do not know the base URL for your API. They cannot construct valid request URLs, rendering the entire spec unusable. Add at least your production server URL.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'high',\n guidance: {\n impact:\n 'Without a servers array, AI agents cannot determine the base URL for your API. Even if your endpoints are perfectly documented, agents cannot construct valid request URLs, rendering the entire OpenAPI spec unusable.',\n fix: 'Add a servers array to your OpenAPI spec with at least your production server URL. Include a description for clarity.',\n code: `\"servers\": [\n {\n \"url\": \"https://yoursite.com/api\",\n \"description\": \"Production server\"\n }\n]`,\n effort: 'trivial',\n docsUrl: 'https://swagger.io/specification/#server-object',\n tags: ['openapi', 'servers', 'api'],\n },\n };\n\n async audit(ctx: CheckContext): Promise<AuditResult> {\n const spec = getOpenApiSpec(ctx);\n if (!spec) {\n return this.fail(\n 'No parseable OpenAPI JSON spec found.',\n 'servers array has at least one entry with a reachable url',\n 'No spec',\n {\n priority: 'high',\n description: OpenApiServersAudit.meta.description,\n code: `\"servers\": [\\n {\\n \"url\": \"https://yoursite.com/api\",\\n \"description\": \"Production server\"\\n }\\n]`,\n },\n );\n }\n\n const servers = spec['servers'];\n if (!Array.isArray(servers) || servers.length === 0) {\n return this.fail(\n 'No servers array in OpenAPI spec.',\n 'servers array has at least one entry with a reachable url',\n 'No servers array',\n {\n priority: 'high',\n description: OpenApiServersAudit.meta.description,\n code: `\"servers\": [\\n {\\n \"url\": \"https://yoursite.com/api\",\\n \"description\": \"Production server\"\\n }\\n]`,\n },\n );\n }\n\n const firstWithUrl = servers.find(\n (s) => isObject(s) && typeof s['url'] === 'string' && s['url'],\n );\n if (!firstWithUrl) {\n return this.fail(\n 'servers array has no entries with a url field.',\n 'servers array has at least one entry with a reachable url',\n 'No url in servers entries',\n {\n priority: 'high',\n description: OpenApiServersAudit.meta.description,\n code: `\"servers\": [\\n {\\n \"url\": \"https://yoursite.com/api\",\\n \"description\": \"Production server\"\\n }\\n]`,\n },\n );\n }\n\n const serverUrl = (firstWithUrl as Record<string, unknown>)['url'] as string;\n\n try {\n const result = await ctx.fetch({ url: serverUrl });\n if (result.status >= 200 && result.status < 400) {\n return this.pass(\n `Server URL ${serverUrl} is reachable (HTTP ${result.status}).`,\n 'servers array has at least one entry with a reachable url',\n `${serverUrl} -> HTTP ${result.status}`,\n );\n }\n return this.warn(\n `Server URL ${serverUrl} returned HTTP ${result.status}.`,\n 'servers array has at least one entry with a reachable url',\n `${serverUrl} -> HTTP ${result.status}`,\n {\n priority: 'high',\n description: OpenApiServersAudit.meta.description,\n code: `\"servers\": [\\n {\\n \"url\": \"https://yoursite.com/api\",\\n \"description\": \"Production server\"\\n }\\n]`,\n },\n );\n } catch {\n return this.warn(\n `Server URL ${serverUrl} could not be reached.`,\n 'servers array has at least one entry with a reachable url',\n `${serverUrl} -> unreachable`,\n {\n priority: 'high',\n description: OpenApiServersAudit.meta.description,\n code: `\"servers\": [\\n {\\n \"url\": \"https://yoursite.com/api\",\\n \"description\": \"Production server\"\\n }\\n]`,\n },\n );\n }\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nfunction tryParseJson(body: string): unknown {\n try {\n return JSON.parse(body);\n } catch {\n return undefined;\n }\n}\n\nfunction isObject(val: unknown): val is Record<string, unknown> {\n return typeof val === 'object' && val !== null && !Array.isArray(val);\n}\n\ntype OpenApiPaths = Record<string, Record<string, unknown>>;\ntype OpenApiOperation = Record<string, unknown>;\n\nconst HTTP_METHODS = ['get', 'post', 'put', 'patch', 'delete', 'options', 'head', 'trace'];\n\nfunction getOpenApiSpec(ctx: {\n rootFiles: Record<string, { status: number; body: string }>;\n}): Record<string, unknown> | undefined {\n const jsonResult = ctx.rootFiles['/openapi.json'];\n if (jsonResult && jsonResult.status === 200 && jsonResult.body) {\n const parsed = tryParseJson(jsonResult.body);\n if (isObject(parsed)) return parsed;\n }\n return undefined;\n}\n\nfunction getOperations(\n spec: Record<string, unknown>,\n): Array<{ path: string; method: string; op: OpenApiOperation }> {\n const paths = spec['paths'] as OpenApiPaths | undefined;\n if (!isObject(paths)) return [];\n\n const ops: Array<{ path: string; method: string; op: OpenApiOperation }> = [];\n for (const [path, pathItem] of Object.entries(paths)) {\n if (!isObject(pathItem)) continue;\n for (const method of HTTP_METHODS) {\n const op = pathItem[method];\n if (isObject(op)) {\n ops.push({ path, method, op: op as OpenApiOperation });\n }\n }\n }\n return ops;\n}\n\nexport class OpenApiSchemasAudit extends Audit {\n static override meta: AuditMeta = {\n id: '5.6',\n category: 'agent-tools',\n title: 'OpenAPI request/response schemas',\n failureTitle: 'OpenAPI request/response schemas',\n description:\n 'Without request/response schemas, AI agents must guess the data format for your endpoints. This leads to malformed requests and failed API calls. Define JSON schemas for all request bodies and responses.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'Without request/response schemas, AI agents must guess what data to send and what to expect back. This leads to malformed requests, failed API calls, and agents that cannot reliably use your endpoints.',\n fix: 'Define JSON Schema for all request bodies (POST/PUT/PATCH) and response bodies in your OpenAPI spec. Include property types, required fields, and format hints (e.g., \"format\": \"email\").',\n code: `\"post\": {\n \"operationId\": \"submitContact\",\n \"requestBody\": {\n \"required\": true,\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"type\": \"object\",\n \"required\": [\"email\", \"message\"],\n \"properties\": {\n \"name\": { \"type\": \"string\" },\n \"email\": { \"type\": \"string\", \"format\": \"email\" },\n \"message\": { \"type\": \"string\" }\n }\n }\n }\n }\n },\n \"responses\": {\n \"200\": {\n \"description\": \"Success\",\n \"content\": {\n \"application/json\": {\n \"schema\": {\n \"type\": \"object\",\n \"properties\": {\n \"success\": { \"type\": \"boolean\" },\n \"id\": { \"type\": \"string\" }\n }\n }\n }\n }\n }\n }\n}`,\n effort: 'moderate',\n docsUrl: 'https://swagger.io/specification/#schema-object',\n tags: ['openapi', 'schemas', 'api', 'validation'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const spec = getOpenApiSpec(ctx);\n if (!spec) {\n return this.fail(\n 'No parseable OpenAPI JSON spec found.',\n 'Operations have requestBody and responses with schema definitions',\n 'No spec',\n {\n priority: 'medium',\n description: OpenApiSchemasAudit.meta.description,\n code: `\"post\": {\\n \"operationId\": \"submitContact\",\\n \"requestBody\": {\\n \"required\": true,\\n \"content\": {\\n \"application/json\": {\\n \"schema\": {\\n \"type\": \"object\",\\n \"required\": [\"email\", \"message\"],\\n \"properties\": {\\n \"name\": { \"type\": \"string\" },\\n \"email\": { \"type\": \"string\", \"format\": \"email\" },\\n \"message\": { \"type\": \"string\" }\\n }\\n }\\n }\\n }\\n },\\n \"responses\": {\\n \"200\": {\\n \"description\": \"Success\",\\n \"content\": {\\n \"application/json\": {\\n \"schema\": {\\n \"type\": \"object\",\\n \"properties\": {\\n \"success\": { \"type\": \"boolean\" },\\n \"id\": { \"type\": \"string\" }\\n }\\n }\\n }\\n }\\n }\\n }\\n}`,\n },\n );\n }\n\n const ops = getOperations(spec);\n if (ops.length === 0) {\n return this.fail(\n 'No operations to check.',\n 'Operations have requestBody and responses with schema definitions',\n '0 operations',\n {\n priority: 'medium',\n description: OpenApiSchemasAudit.meta.description,\n code: `\"post\": {\\n \"operationId\": \"submitContact\",\\n \"requestBody\": {\\n \"required\": true,\\n \"content\": {\\n \"application/json\": {\\n \"schema\": {\\n \"type\": \"object\",\\n \"required\": [\"email\", \"message\"],\\n \"properties\": {\\n \"name\": { \"type\": \"string\" },\\n \"email\": { \"type\": \"string\", \"format\": \"email\" },\\n \"message\": { \"type\": \"string\" }\\n }\\n }\\n }\\n }\\n },\\n \"responses\": {\\n \"200\": {\\n \"description\": \"Success\",\\n \"content\": {\\n \"application/json\": {\\n \"schema\": {\\n \"type\": \"object\",\\n \"properties\": {\\n \"success\": { \"type\": \"boolean\" },\\n \"id\": { \"type\": \"string\" }\\n }\\n }\\n }\\n }\\n }\\n }\\n}`,\n },\n );\n }\n\n let withRequestSchema = 0;\n let withResponseSchema = 0;\n let writeMethods = 0; // POST/PUT/PATCH that should have requestBody\n\n for (const { method, op } of ops) {\n if (['post', 'put', 'patch'].includes(method)) {\n writeMethods++;\n const rb = op['requestBody'];\n if (isObject(rb)) {\n const content = rb['content'];\n if (isObject(content)) {\n for (const mediaType of Object.values(content)) {\n if (isObject(mediaType) && mediaType['schema']) {\n withRequestSchema++;\n break;\n }\n }\n }\n }\n }\n\n const responses = op['responses'];\n if (isObject(responses)) {\n for (const resp of Object.values(responses)) {\n if (isObject(resp)) {\n const content = (resp as Record<string, unknown>)['content'];\n if (isObject(content)) {\n for (const mediaType of Object.values(content)) {\n if (isObject(mediaType) && mediaType['schema']) {\n withResponseSchema++;\n break;\n }\n }\n break; // only need one response with schema\n }\n }\n }\n }\n }\n\n const totalCheckable = ops.length;\n const hasGoodCoverage =\n withResponseSchema >= totalCheckable * 0.5 &&\n (writeMethods === 0 || withRequestSchema >= writeMethods * 0.5);\n\n if (\n withResponseSchema === totalCheckable &&\n (writeMethods === 0 || withRequestSchema === writeMethods)\n ) {\n return this.pass(\n `All operations have response schemas${writeMethods > 0 ? ` and all ${writeMethods} write operation(s) have request schemas` : ''}.`,\n 'Operations have requestBody and responses with schema definitions',\n `${withResponseSchema}/${totalCheckable} response schemas, ${withRequestSchema}/${writeMethods} request schemas`,\n );\n }\n\n const recommendation = {\n priority: 'medium' as const,\n description: OpenApiSchemasAudit.meta.description,\n code: `\"post\": {\\n \"operationId\": \"submitContact\",\\n \"requestBody\": {\\n \"required\": true,\\n \"content\": {\\n \"application/json\": {\\n \"schema\": {\\n \"type\": \"object\",\\n \"required\": [\"email\", \"message\"],\\n \"properties\": {\\n \"name\": { \"type\": \"string\" },\\n \"email\": { \"type\": \"string\", \"format\": \"email\" },\\n \"message\": { \"type\": \"string\" }\\n }\\n }\\n }\\n }\\n },\\n \"responses\": {\\n \"200\": {\\n \"description\": \"Success\",\\n \"content\": {\\n \"application/json\": {\\n \"schema\": {\\n \"type\": \"object\",\\n \"properties\": {\\n \"success\": { \"type\": \"boolean\" },\\n \"id\": { \"type\": \"string\" }\\n }\\n }\\n }\\n }\\n }\\n }\\n}`,\n };\n\n if (hasGoodCoverage) {\n return this.warn(\n `Partial schema coverage: ${withResponseSchema}/${totalCheckable} response schemas, ${withRequestSchema}/${writeMethods} request schemas.`,\n 'Operations have requestBody and responses with schema definitions',\n `${withResponseSchema}/${totalCheckable} response, ${withRequestSchema}/${writeMethods} request`,\n recommendation,\n );\n }\n\n return this.fail(\n `Low schema coverage: ${withResponseSchema}/${totalCheckable} response schemas, ${withRequestSchema}/${writeMethods} request schemas.`,\n 'Operations have requestBody and responses with schema definitions',\n `${withResponseSchema}/${totalCheckable} response, ${withRequestSchema}/${writeMethods} request`,\n recommendation,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nfunction tryParseJson(body: string): unknown {\n try {\n return JSON.parse(body);\n } catch {\n return undefined;\n }\n}\n\nfunction isObject(val: unknown): val is Record<string, unknown> {\n return typeof val === 'object' && val !== null && !Array.isArray(val);\n}\n\nexport class AiCatalogExistsAudit extends Audit {\n static override meta: AuditMeta = {\n id: '5.7',\n category: 'agent-tools',\n title: 'AI Catalog exists',\n failureTitle: 'AI Catalog exists',\n description:\n 'The AI catalog is the central discovery file that tells AI agents what capabilities your site offers. Think of it as a table of contents for your APIs, tools, and services. Without it, agents must probe multiple endpoints to understand what your site can do.',\n scoreDisplayMode: 'binary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'Without an AI catalog, agents must probe multiple endpoints to discover your services. This wastes time, increases error rates, and often results in agents skipping your site entirely in favor of competitors with clear service listings.',\n fix: \"Create a /.well-known/ai-catalog.json file listing your site name, description, capabilities, and a services array with each service's name, description, URL, and type.\",\n code: `// /.well-known/ai-catalog.json\n{\n \"version\": \"1.0\",\n \"name\": \"Your Site\",\n \"description\": \"What your site does\",\n \"capabilities\": [\"search\", \"contact\", \"product-info\"],\n \"services\": [\n {\n \"name\": \"Search\",\n \"description\": \"Search our content\",\n \"url\": \"https://yoursite.com/api/search\",\n \"type\": \"rest\"\n }\n ]\n}`,\n effort: 'easy',\n tags: ['ai-catalog', 'discovery', 'agent-protocol'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const result = ctx.rootFiles['/.well-known/ai-catalog.json'];\n if (!result || result.status !== 200 || !result.body) {\n return this.fail(\n '/.well-known/ai-catalog.json not found or not accessible.',\n '/.well-known/ai-catalog.json returns 200 with valid JSON containing services array',\n result ? `HTTP ${result.status}` : 'Not fetched',\n {\n priority: 'medium',\n description: AiCatalogExistsAudit.meta.description,\n code: `// /.well-known/ai-catalog.json\\n{\\n \"version\": \"1.0\",\\n \"name\": \"Your Site\",\\n \"description\": \"What your site does\",\\n \"capabilities\": [\"search\", \"contact\", \"product-info\"],\\n \"owner\": \"Your Company\",\\n \"contact\": \"hello@yoursite.com\",\\n \"lastUpdated\": \"2026-01-01\",\\n \"services\": [\\n {\\n \"name\": \"Search\",\\n \"description\": \"Search our content\",\\n \"url\": \"https://yoursite.com/api/search\",\\n \"type\": \"rest\"\\n },\\n {\\n \"name\": \"Contact\",\\n \"description\": \"Submit inquiries\",\\n \"url\": \"https://yoursite.com/api/contact\",\\n \"type\": \"rest\"\\n }\\n ]\\n}`,\n },\n );\n }\n\n const parsed = tryParseJson(result.body);\n if (!isObject(parsed)) {\n return this.fail(\n 'ai-catalog.json is not valid JSON.',\n '/.well-known/ai-catalog.json returns 200 with valid JSON containing services array',\n 'Invalid JSON',\n {\n priority: 'medium',\n description: AiCatalogExistsAudit.meta.description,\n code: `// /.well-known/ai-catalog.json\\n{\\n \"version\": \"1.0\",\\n \"name\": \"Your Site\",\\n \"description\": \"What your site does\",\\n \"capabilities\": [\"search\", \"contact\", \"product-info\"],\\n \"owner\": \"Your Company\",\\n \"contact\": \"hello@yoursite.com\",\\n \"lastUpdated\": \"2026-01-01\",\\n \"services\": [\\n {\\n \"name\": \"Search\",\\n \"description\": \"Search our content\",\\n \"url\": \"https://yoursite.com/api/search\",\\n \"type\": \"rest\"\\n },\\n {\\n \"name\": \"Contact\",\\n \"description\": \"Submit inquiries\",\\n \"url\": \"https://yoursite.com/api/contact\",\\n \"type\": \"rest\"\\n }\\n ]\\n}`,\n },\n );\n }\n\n if (!Array.isArray(parsed['services'])) {\n return this.fail(\n 'ai-catalog.json does not contain a services array.',\n '/.well-known/ai-catalog.json returns 200 with valid JSON containing services array',\n 'No services array',\n {\n priority: 'medium',\n description: AiCatalogExistsAudit.meta.description,\n code: `// /.well-known/ai-catalog.json\\n{\\n \"version\": \"1.0\",\\n \"name\": \"Your Site\",\\n \"description\": \"What your site does\",\\n \"capabilities\": [\"search\", \"contact\", \"product-info\"],\\n \"owner\": \"Your Company\",\\n \"contact\": \"hello@yoursite.com\",\\n \"lastUpdated\": \"2026-01-01\",\\n \"services\": [\\n {\\n \"name\": \"Search\",\\n \"description\": \"Search our content\",\\n \"url\": \"https://yoursite.com/api/search\",\\n \"type\": \"rest\"\\n },\\n {\\n \"name\": \"Contact\",\\n \"description\": \"Submit inquiries\",\\n \"url\": \"https://yoursite.com/api/contact\",\\n \"type\": \"rest\"\\n }\\n ]\\n}`,\n },\n );\n }\n\n return this.pass(\n `AI catalog found with ${(parsed['services'] as unknown[]).length} service(s).`,\n '/.well-known/ai-catalog.json returns 200 with valid JSON containing services array',\n `Valid JSON with ${(parsed['services'] as unknown[]).length} service(s)`,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nfunction tryParseJson(body: string): unknown {\n try {\n return JSON.parse(body);\n } catch {\n return undefined;\n }\n}\n\nfunction isObject(val: unknown): val is Record<string, unknown> {\n return typeof val === 'object' && val !== null && !Array.isArray(val);\n}\n\nexport class AiCatalogMetadataAudit extends Audit {\n static override meta: AuditMeta = {\n id: '5.8',\n category: 'agent-tools',\n title: 'AI Catalog complete metadata',\n failureTitle: 'AI Catalog complete metadata',\n description:\n 'Complete metadata helps AI agents understand who owns the service, when it was last updated, and what it can do. Missing fields reduce agent confidence in your services and may cause them to skip your site in favor of better-documented alternatives.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'Incomplete metadata reduces agent confidence in your services. Agents may skip your site when fields like owner, contact, or lastUpdated are missing because they cannot verify freshness or accountability.',\n fix: 'Add all required metadata fields to your ai-catalog.json: version, name, description, capabilities, owner, contact, and lastUpdated.',\n code: `{\n \"version\": \"1.0\",\n \"name\": \"Your Site\",\n \"description\": \"Brief description of your site and services\",\n \"capabilities\": [\"search\", \"contact\", \"product-info\"],\n \"owner\": \"Your Company Name\",\n \"contact\": \"hello@yoursite.com\",\n \"lastUpdated\": \"2026-01-01\",\n \"services\": []\n}`,\n effort: 'trivial',\n tags: ['ai-catalog', 'metadata', 'agent-protocol'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const result = ctx.rootFiles['/.well-known/ai-catalog.json'];\n if (!result || result.status !== 200 || !result.body) {\n return this.fail(\n 'ai-catalog.json not found.',\n 'Has version, name, description, capabilities, owner, contact, lastUpdated',\n 'No ai-catalog.json',\n {\n priority: 'medium',\n description: AiCatalogMetadataAudit.meta.description,\n code: `{\\n \"version\": \"1.0\",\\n \"name\": \"Your Site\",\\n \"description\": \"Brief description of your site and services\",\\n \"capabilities\": [\"search\", \"contact\", \"product-info\"],\\n \"owner\": \"Your Company Name\",\\n \"contact\": \"hello@yoursite.com\",\\n \"lastUpdated\": \"2026-01-01\",\\n \"services\": []\\n}`,\n },\n );\n }\n\n const parsed = tryParseJson(result.body);\n if (!isObject(parsed)) {\n return this.fail(\n 'ai-catalog.json is not valid JSON.',\n 'Has version, name, description, capabilities, owner, contact, lastUpdated',\n 'Invalid JSON',\n {\n priority: 'medium',\n description: AiCatalogMetadataAudit.meta.description,\n code: `{\\n \"version\": \"1.0\",\\n \"name\": \"Your Site\",\\n \"description\": \"Brief description of your site and services\",\\n \"capabilities\": [\"search\", \"contact\", \"product-info\"],\\n \"owner\": \"Your Company Name\",\\n \"contact\": \"hello@yoursite.com\",\\n \"lastUpdated\": \"2026-01-01\",\\n \"services\": []\\n}`,\n },\n );\n }\n\n const requiredFields = [\n 'version',\n 'name',\n 'description',\n 'capabilities',\n 'owner',\n 'contact',\n 'lastUpdated',\n ];\n const present = requiredFields.filter(\n (f) => parsed[f] !== undefined && parsed[f] !== null && parsed[f] !== '',\n );\n const missing = requiredFields.filter((f) => !present.includes(f));\n\n if (missing.length === 0) {\n return this.pass(\n 'AI catalog has all required metadata fields.',\n 'Has version, name, description, capabilities, owner, contact, lastUpdated',\n `All ${requiredFields.length} fields present`,\n );\n }\n\n const recommendation = {\n priority: 'medium' as const,\n description: AiCatalogMetadataAudit.meta.description,\n code: `{\\n \"version\": \"1.0\",\\n \"name\": \"Your Site\",\\n \"description\": \"Brief description of your site and services\",\\n \"capabilities\": [\"search\", \"contact\", \"product-info\"],\\n \"owner\": \"Your Company Name\",\\n \"contact\": \"hello@yoursite.com\",\\n \"lastUpdated\": \"2026-01-01\",\\n \"services\": []\\n}`,\n };\n\n if (present.length >= requiredFields.length / 2) {\n return this.warn(\n `AI catalog is missing metadata fields: ${missing.join(', ')}.`,\n 'Has version, name, description, capabilities, owner, contact, lastUpdated',\n `${present.length}/${requiredFields.length} fields; missing: ${missing.join(', ')}`,\n recommendation,\n );\n }\n\n return this.fail(\n `AI catalog is missing most metadata fields: ${missing.join(', ')}.`,\n 'Has version, name, description, capabilities, owner, contact, lastUpdated',\n `${present.length}/${requiredFields.length} fields present`,\n recommendation,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nfunction tryParseJson(body: string): unknown {\n try {\n return JSON.parse(body);\n } catch {\n return undefined;\n }\n}\n\nfunction isObject(val: unknown): val is Record<string, unknown> {\n return typeof val === 'object' && val !== null && !Array.isArray(val);\n}\n\nexport class AiCatalogUrlsAudit extends Audit {\n static override meta: AuditMeta = {\n id: '5.9',\n category: 'agent-tools',\n title: 'AI Catalog service URLs valid',\n failureTitle: 'AI Catalog service URLs valid',\n description:\n 'Broken service URLs in your AI catalog cause agents to fail when trying to use your services, creating a poor user experience. Verify all URLs are correct, deployed, and returning HTTP 200.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'Broken service URLs in your AI catalog cause agents to fail mid-task. Users who asked the agent to interact with your site get errors instead of results, creating a poor experience and lost business.',\n fix: 'Verify every service URL in your ai-catalog.json is deployed, returns HTTP 200, and matches your current production endpoints. Remove or update any stale entries.',\n code: `\"services\": [\n {\n \"name\": \"Search\",\n \"description\": \"Search site content\",\n \"url\": \"https://yoursite.com/api/search\",\n \"type\": \"rest\"\n }\n]`,\n effort: 'trivial',\n tags: ['ai-catalog', 'validation', 'agent-protocol'],\n },\n };\n\n async audit(ctx: CheckContext): Promise<AuditResult> {\n const result = ctx.rootFiles['/.well-known/ai-catalog.json'];\n if (!result || result.status !== 200 || !result.body) {\n return this.fail(\n 'ai-catalog.json not found.',\n 'Each service URL returns HTTP 200',\n 'No ai-catalog.json',\n {\n priority: 'medium',\n description: AiCatalogUrlsAudit.meta.description,\n code: `\"services\": [\\n {\\n \"name\": \"Search\",\\n \"description\": \"Search site content\",\\n \"url\": \"https://yoursite.com/api/search\",\\n \"type\": \"rest\"\\n }\\n]`,\n },\n );\n }\n\n const parsed = tryParseJson(result.body);\n if (!isObject(parsed) || !Array.isArray(parsed['services'])) {\n return this.fail(\n 'ai-catalog.json has no services array.',\n 'Each service URL returns HTTP 200',\n 'No services',\n {\n priority: 'medium',\n description: AiCatalogUrlsAudit.meta.description,\n code: `\"services\": [\\n {\\n \"name\": \"Search\",\\n \"description\": \"Search site content\",\\n \"url\": \"https://yoursite.com/api/search\",\\n \"type\": \"rest\"\\n }\\n]`,\n },\n );\n }\n\n const services = parsed['services'] as unknown[];\n const urls: string[] = [];\n for (const svc of services) {\n if (isObject(svc) && typeof svc['url'] === 'string' && svc['url']) {\n urls.push(svc['url'] as string);\n }\n }\n\n if (urls.length === 0) {\n return this.warn(\n 'No service URLs found in ai-catalog.json.',\n 'Each service URL returns HTTP 200',\n '0 service URLs',\n {\n priority: 'medium',\n description: AiCatalogUrlsAudit.meta.description,\n code: `\"services\": [\\n {\\n \"name\": \"Search\",\\n \"description\": \"Search site content\",\\n \"url\": \"https://yoursite.com/api/search\",\\n \"type\": \"rest\"\\n }\\n]`,\n },\n );\n }\n\n const results = await Promise.all(\n urls.map(async (url) => {\n try {\n const r = await ctx.fetch({ url });\n return { url, status: r.status };\n } catch {\n return { url, status: 0 };\n }\n }),\n );\n\n const reachable = results.filter((r) => r.status === 200).length;\n\n if (reachable === urls.length) {\n return this.pass(\n `All ${urls.length} service URL(s) returned HTTP 200.`,\n 'Each service URL returns HTTP 200',\n `${reachable}/${urls.length} reachable`,\n );\n }\n\n const recommendation = {\n priority: 'medium' as const,\n description: AiCatalogUrlsAudit.meta.description,\n code: `\"services\": [\\n {\\n \"name\": \"Search\",\\n \"description\": \"Search site content\",\\n \"url\": \"https://yoursite.com/api/search\",\\n \"type\": \"rest\"\\n }\\n]`,\n };\n\n if (reachable > 0) {\n const failed = results.filter((r) => r.status !== 200).map((r) => `${r.url} (${r.status})`);\n return this.warn(\n `${reachable}/${urls.length} service URLs reachable. Failed: ${failed.join(', ')}.`,\n 'Each service URL returns HTTP 200',\n `${reachable}/${urls.length} reachable`,\n recommendation,\n );\n }\n\n return this.fail(\n `None of the ${urls.length} service URL(s) returned HTTP 200.`,\n 'Each service URL returns HTTP 200',\n `0/${urls.length} reachable`,\n recommendation,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nfunction tryParseJson(body: string): unknown {\n try {\n return JSON.parse(body);\n } catch {\n return undefined;\n }\n}\n\nfunction isObject(val: unknown): val is Record<string, unknown> {\n return typeof val === 'object' && val !== null && !Array.isArray(val);\n}\n\nexport class AgentsJsonAudit extends Audit {\n static override meta: AuditMeta = {\n id: '5.10',\n category: 'agent-tools',\n title: 'agents.json exists',\n failureTitle: 'agents.json exists',\n description:\n 'agents.json declares what AI agents can do on your site, including authentication methods, rate limits, and supported protocols. It helps agents self-configure before interacting with your services.',\n scoreDisplayMode: 'binary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n \"Without agents.json, AI agents have no way to discover your site's capabilities, authentication requirements, or rate limits. They must probe endpoints blindly, leading to errors and skipped interactions.\",\n fix: 'Create a /.well-known/agents.json file that declares your site name, supported protocols, authentication method, rate limits, and available endpoints.',\n code: `// /.well-known/agents.json\n{\n \"name\": \"Your Site\",\n \"description\": \"Your site description for AI agents\",\n \"protocols\": [\"rest\", \"mcp\"],\n \"authentication\": { \"type\": \"none\" },\n \"rate_limits\": { \"requests_per_minute\": 60 },\n \"endpoints\": [\n {\n \"url\": \"/api/search\",\n \"method\": \"GET\",\n \"description\": \"Search content\"\n }\n ]\n}`,\n effort: 'easy',\n docsUrl: 'https://agentsjson.org/',\n tags: ['agents-json', 'discovery', 'agent-protocol'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const result = ctx.rootFiles['/.well-known/agents.json'];\n if (!result || result.status !== 200 || !result.body) {\n return this.fail(\n '/.well-known/agents.json not found or not accessible.',\n '/.well-known/agents.json returns 200 with valid JSON',\n result ? `HTTP ${result.status}` : 'Not fetched',\n {\n priority: 'medium',\n description: AgentsJsonAudit.meta.description,\n code: `// /.well-known/agents.json\\n{\\n \"name\": \"Your Site\",\\n \"description\": \"Your site description for AI agents\",\\n \"protocols\": [\"rest\", \"mcp\"],\\n \"authentication\": {\\n \"type\": \"none\"\\n },\\n \"rate_limits\": {\\n \"requests_per_minute\": 60\\n },\\n \"endpoints\": [\\n {\\n \"url\": \"/api/search\",\\n \"method\": \"GET\",\\n \"description\": \"Search content\"\\n }\\n ]\\n}`,\n },\n );\n }\n\n const parsed = tryParseJson(result.body);\n if (!isObject(parsed) && !Array.isArray(parsed)) {\n return this.fail(\n 'agents.json is not valid JSON.',\n '/.well-known/agents.json returns 200 with valid JSON',\n 'Invalid JSON',\n {\n priority: 'medium',\n description: AgentsJsonAudit.meta.description,\n code: `// /.well-known/agents.json\\n{\\n \"name\": \"Your Site\",\\n \"description\": \"Your site description for AI agents\",\\n \"protocols\": [\"rest\", \"mcp\"],\\n \"authentication\": {\\n \"type\": \"none\"\\n },\\n \"rate_limits\": {\\n \"requests_per_minute\": 60\\n },\\n \"endpoints\": [\\n {\\n \"url\": \"/api/search\",\\n \"method\": \"GET\",\\n \"description\": \"Search content\"\\n }\\n ]\\n}`,\n },\n );\n }\n\n return this.pass(\n 'agents.json found with valid JSON content.',\n '/.well-known/agents.json returns 200 with valid JSON',\n 'Valid JSON at /.well-known/agents.json',\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nfunction tryParseJson(body: string): unknown {\n try {\n return JSON.parse(body);\n } catch {\n return undefined;\n }\n}\n\nfunction isObject(val: unknown): val is Record<string, unknown> {\n return typeof val === 'object' && val !== null && !Array.isArray(val);\n}\n\nexport class AiPluginJsonAudit extends Audit {\n static override meta: AuditMeta = {\n id: '5.11',\n category: 'agent-tools',\n title: 'ai-plugin.json exists',\n failureTitle: 'ai-plugin.json exists',\n description:\n 'ai-plugin.json is the ChatGPT plugin manifest format. Even if you do not build a ChatGPT plugin, having this file helps AI agents understand your site as a tool with human-readable and model-readable names, logos, and API references.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'ai-plugin.json is the standard manifest used by ChatGPT and other AI platforms to register your site as a tool. Without it, your site cannot be installed as a plugin, and agents lose the human-readable and model-readable names needed for reliable interactions.',\n fix: 'Create a /.well-known/ai-plugin.json with at minimum schema_version, name_for_human, name_for_model, description_for_human, description_for_model, auth, and an api reference pointing to your OpenAPI spec.',\n code: `// /.well-known/ai-plugin.json\n{\n \"schema_version\": \"v1\",\n \"name_for_human\": \"Your Site Name\",\n \"name_for_model\": \"your_site\",\n \"description_for_human\": \"What your site does for users.\",\n \"description_for_model\": \"Use this plugin to search content and submit inquiries.\",\n \"auth\": { \"type\": \"none\" },\n \"api\": {\n \"type\": \"openapi\",\n \"url\": \"https://yoursite.com/openapi.json\"\n },\n \"logo_url\": \"https://yoursite.com/logo.png\",\n \"contact_email\": \"hello@yoursite.com\"\n}`,\n effort: 'easy',\n docsUrl: 'https://platform.openai.com/docs/plugins/getting-started/plugin-manifest',\n tags: ['ai-plugin', 'chatgpt', 'discovery', 'agent-protocol'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const result = ctx.rootFiles['/.well-known/ai-plugin.json'];\n if (!result || result.status !== 200 || !result.body) {\n return this.fail(\n '/.well-known/ai-plugin.json not found or not accessible.',\n '/.well-known/ai-plugin.json returns 200 with valid JSON containing schema_version, name_for_human, name_for_model',\n result ? `HTTP ${result.status}` : 'Not fetched',\n {\n priority: 'medium',\n description: AiPluginJsonAudit.meta.description,\n code: `// /.well-known/ai-plugin.json\\n{\\n \"schema_version\": \"v1\",\\n \"name_for_human\": \"Your Site Name\",\\n \"name_for_model\": \"your_site\",\\n \"description_for_human\": \"What your site does for users.\",\\n \"description_for_model\": \"Use this plugin to search content, submit inquiries, and get product details from Your Site.\",\\n \"auth\": { \"type\": \"none\" },\\n \"api\": {\\n \"type\": \"openapi\",\\n \"url\": \"https://yoursite.com/openapi.json\"\\n },\\n \"logo_url\": \"https://yoursite.com/logo.png\",\\n \"contact_email\": \"hello@yoursite.com\"\\n}`,\n },\n );\n }\n\n const parsed = tryParseJson(result.body);\n if (!isObject(parsed)) {\n return this.fail(\n 'ai-plugin.json is not valid JSON.',\n '/.well-known/ai-plugin.json returns 200 with valid JSON containing schema_version, name_for_human, name_for_model',\n 'Invalid JSON',\n {\n priority: 'medium',\n description: AiPluginJsonAudit.meta.description,\n code: `// /.well-known/ai-plugin.json\\n{\\n \"schema_version\": \"v1\",\\n \"name_for_human\": \"Your Site Name\",\\n \"name_for_model\": \"your_site\",\\n \"description_for_human\": \"What your site does for users.\",\\n \"description_for_model\": \"Use this plugin to search content, submit inquiries, and get product details from Your Site.\",\\n \"auth\": { \"type\": \"none\" },\\n \"api\": {\\n \"type\": \"openapi\",\\n \"url\": \"https://yoursite.com/openapi.json\"\\n },\\n \"logo_url\": \"https://yoursite.com/logo.png\",\\n \"contact_email\": \"hello@yoursite.com\"\\n}`,\n },\n );\n }\n\n const requiredFields = ['schema_version', 'name_for_human', 'name_for_model'];\n const missing = requiredFields.filter((f) => typeof parsed[f] !== 'string' || !parsed[f]);\n\n if (missing.length === 0) {\n return this.pass(\n 'ai-plugin.json found with all required fields.',\n '/.well-known/ai-plugin.json returns 200 with valid JSON containing schema_version, name_for_human, name_for_model',\n // requiredFields guarantees these three are non-empty strings here.\n `schema_version=${parsed['schema_version'] as string}, name_for_human=${parsed['name_for_human'] as string}, name_for_model=${parsed['name_for_model'] as string}`,\n );\n }\n\n const recommendation = {\n priority: 'medium' as const,\n description: AiPluginJsonAudit.meta.description,\n code: `// /.well-known/ai-plugin.json\\n{\\n \"schema_version\": \"v1\",\\n \"name_for_human\": \"Your Site Name\",\\n \"name_for_model\": \"your_site\",\\n \"description_for_human\": \"What your site does for users.\",\\n \"description_for_model\": \"Use this plugin to search content, submit inquiries, and get product details from Your Site.\",\\n \"auth\": { \"type\": \"none\" },\\n \"api\": {\\n \"type\": \"openapi\",\\n \"url\": \"https://yoursite.com/openapi.json\"\\n },\\n \"logo_url\": \"https://yoursite.com/logo.png\",\\n \"contact_email\": \"hello@yoursite.com\"\\n}`,\n };\n\n if (missing.length < requiredFields.length) {\n return this.warn(\n `ai-plugin.json is missing fields: ${missing.join(', ')}.`,\n '/.well-known/ai-plugin.json returns 200 with valid JSON containing schema_version, name_for_human, name_for_model',\n `Missing: ${missing.join(', ')}`,\n recommendation,\n );\n }\n\n return this.fail(\n `ai-plugin.json is missing all required fields: ${missing.join(', ')}.`,\n '/.well-known/ai-plugin.json returns 200 with valid JSON containing schema_version, name_for_human, name_for_model',\n `Missing: ${missing.join(', ')}`,\n recommendation,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nfunction tryParseJson(body: string): unknown {\n try {\n return JSON.parse(body);\n } catch {\n return undefined;\n }\n}\n\nfunction isObject(val: unknown): val is Record<string, unknown> {\n return typeof val === 'object' && val !== null && !Array.isArray(val);\n}\n\nexport class McpDiscoveryAudit extends Audit {\n static override meta: AuditMeta = {\n id: '5.12',\n category: 'agent-tools',\n title: 'MCP server discovery file',\n failureTitle: 'MCP server discovery file',\n description:\n 'MCP (Model Context Protocol) lets AI assistants like Claude and ChatGPT directly integrate your site as a tool. Publishing an MCP discovery file means users can add your site as a tool in their AI assistant with a single URL, enabling rich interactions beyond simple browsing.',\n scoreDisplayMode: 'binary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'MCP (Model Context Protocol) is how AI assistants like Claude and ChatGPT register your site as an interactive tool. Without a discovery file, users cannot add your site as an MCP server in their AI assistant, missing out on rich tool-based interactions.',\n fix: 'Create a /.well-known/mcp/servers.json file listing your MCP server(s) with name, description, URL, transport type, and capabilities.',\n code: `// /.well-known/mcp/servers.json\n{\n \"servers\": [\n {\n \"name\": \"Your Site MCP\",\n \"description\": \"Search content and submit inquiries\",\n \"url\": \"https://yoursite.com/mcp\",\n \"transport\": \"streamable-http\",\n \"capabilities\": {\n \"tools\": true,\n \"resources\": true\n }\n }\n ]\n}`,\n effort: 'easy',\n docsUrl: 'https://modelcontextprotocol.io/specification/2025-03-26/basic/transports',\n tags: ['mcp', 'discovery', 'agent-protocol'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n // 1. Standard MCP Discovery (/.well-known/mcp/servers.json)\n const result = ctx.rootFiles['/.well-known/mcp/servers.json'];\n if (result && result.status === 200 && result.body) {\n const parsed = tryParseJson(result.body);\n if (!isObject(parsed)) {\n return this.fail(\n 'mcp/servers.json is not valid JSON.',\n '/.well-known/mcp/servers.json returns 200 with valid JSON containing servers array',\n 'Invalid JSON',\n {\n priority: 'medium',\n description: McpDiscoveryAudit.meta.description,\n code: McpDiscoveryAudit.meta.guidance?.code,\n },\n );\n }\n\n if (!Array.isArray(parsed['servers'])) {\n return this.fail(\n 'mcp/servers.json does not contain a servers array.',\n '/.well-known/mcp/servers.json returns 200 with valid JSON containing servers array',\n 'No servers array',\n {\n priority: 'medium',\n description: McpDiscoveryAudit.meta.description,\n code: McpDiscoveryAudit.meta.guidance?.code,\n },\n );\n }\n\n const count = (parsed['servers'] as unknown[]).length;\n return this.pass(\n `MCP servers.json found with ${count} server(s).`,\n '/.well-known/mcp/servers.json returns 200 with valid JSON containing servers array',\n `Valid JSON with ${count} server(s)`,\n );\n }\n\n // 2. Universal Commerce Protocol (UCP / MCP) Discovery (/.well-known/ucp)\n const ucpResult = ctx.rootFiles['/.well-known/ucp'];\n if (ucpResult && ucpResult.status === 200 && ucpResult.body) {\n const ucpParsed = tryParseJson(ucpResult.body);\n if (isObject(ucpParsed)) {\n const ucpObj = (ucpParsed['ucp'] ?? ucpParsed) as Record<string, unknown>;\n const services = (ucpParsed['services'] || ucpObj['services']) as Record<string, unknown> | undefined;\n const capabilities = (ucpParsed['capabilities'] || ucpObj['capabilities']) as Record<string, unknown> | undefined;\n const svcCount = services ? Object.keys(services).length : 0;\n const capCount = capabilities ? Object.keys(capabilities).length : 0;\n return this.pass(\n `Universal Commerce Protocol (UCP/MCP) discovery profile found with ${svcCount} services and ${capCount} capabilities.`,\n '/.well-known/mcp/servers.json or /.well-known/ucp returns 200 with valid agent protocol JSON',\n `UCP/MCP Profile (v${ucpObj['version'] ?? 'stable'}, ${capCount} capabilities)`,\n );\n }\n }\n\n return this.fail(\n '/.well-known/mcp/servers.json not found or not accessible.',\n '/.well-known/mcp/servers.json returns 200 with valid JSON containing servers array',\n result ? `HTTP ${result.status}` : 'Not fetched',\n {\n priority: 'medium',\n description: McpDiscoveryAudit.meta.description,\n code: McpDiscoveryAudit.meta.guidance?.code,\n },\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nfunction tryParseJson(body: string): unknown {\n try {\n return JSON.parse(body);\n } catch {\n return undefined;\n }\n}\n\nfunction isObject(val: unknown): val is Record<string, unknown> {\n return typeof val === 'object' && val !== null && !Array.isArray(val);\n}\n\nexport class McpEndpointAudit extends Audit {\n static override meta: AuditMeta = {\n id: '5.13',\n category: 'agent-tools',\n title: 'MCP endpoint functional',\n failureTitle: 'MCP endpoint functional',\n description:\n 'Your MCP server must respond to JSON-RPC 2.0 initialize requests for AI assistants to connect. If the endpoint is down or misconfigured, agents cannot use your MCP tools. Verify the server is running and accepts POST requests with Content-Type: application/json.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'high',\n guidance: {\n impact:\n 'If your MCP endpoint does not respond to JSON-RPC 2.0 initialize requests, AI assistants cannot connect to your server at all. Users who try to add your site as a tool will see connection failures, and agents will permanently skip your server.',\n fix: 'Ensure your MCP server is running, accepts POST requests with Content-Type: application/json, and correctly handles the JSON-RPC 2.0 \"initialize\" method by returning a valid response with protocolVersion, serverInfo, and capabilities.',\n code: `// Expected request:\nPOST /mcp\nContent-Type: application/json\n\n{\n \"jsonrpc\": \"2.0\",\n \"id\": 1,\n \"method\": \"initialize\",\n \"params\": {\n \"protocolVersion\": \"2024-11-05\",\n \"capabilities\": {},\n \"clientInfo\": { \"name\": \"test\", \"version\": \"1.0.0\" }\n }\n}\n\n// Expected response:\n{\n \"jsonrpc\": \"2.0\",\n \"id\": 1,\n \"result\": {\n \"protocolVersion\": \"2024-11-05\",\n \"serverInfo\": { \"name\": \"your-server\", \"version\": \"1.0.0\" },\n \"capabilities\": { \"tools\": {} }\n }\n}`,\n effort: 'complex',\n docsUrl: 'https://modelcontextprotocol.io/specification/2025-03-26/basic/lifecycle',\n tags: ['mcp', 'endpoint', 'json-rpc', 'agent-protocol'],\n },\n };\n\n async audit(ctx: CheckContext): Promise<AuditResult> {\n let targetEndpointUrl: string | undefined;\n\n // 1. Standard MCP Discovery (/.well-known/mcp/servers.json)\n const result = ctx.rootFiles['/.well-known/mcp/servers.json'];\n if (result && result.status === 200 && result.body) {\n const parsed = tryParseJson(result.body);\n if (!isObject(parsed) || !Array.isArray(parsed['servers'])) {\n return this.fail(\n 'servers.json has no servers array.',\n 'MCP server URL responds to JSON-RPC initialize request',\n 'No servers array',\n {\n priority: 'high',\n description: McpEndpointAudit.meta.description,\n code: McpEndpointAudit.meta.guidance?.code,\n },\n );\n }\n const servers = parsed['servers'] as unknown[];\n const serverUrl = servers.find((s) => isObject(s) && typeof s['url'] === 'string' && s['url']);\n if (!serverUrl || !isObject(serverUrl)) {\n return this.fail(\n 'No server URL found in servers.json.',\n 'MCP server URL responds to JSON-RPC initialize request',\n 'No server URL',\n {\n priority: 'high',\n description: McpEndpointAudit.meta.description,\n code: McpEndpointAudit.meta.guidance?.code,\n },\n );\n }\n targetEndpointUrl = (serverUrl as Record<string, unknown>)['url'] as string;\n }\n\n // 2. Universal Commerce Protocol (UCP / MCP) Discovery (/.well-known/ucp)\n if (!targetEndpointUrl) {\n const ucpResult = ctx.rootFiles['/.well-known/ucp'];\n if (ucpResult && ucpResult.status === 200 && ucpResult.body) {\n const ucpParsed = tryParseJson(ucpResult.body);\n if (isObject(ucpParsed)) {\n const ucpObj = (ucpParsed['ucp'] ?? ucpParsed) as Record<string, unknown>;\n const services = (ucpParsed['services'] || ucpObj['services']) as Record<string, unknown> | undefined;\n if (services) {\n for (const key of Object.keys(services)) {\n const svcList = services[key];\n if (Array.isArray(svcList)) {\n for (const svc of svcList) {\n if (isObject(svc) && svc['transport'] === 'mcp' && typeof svc['endpoint'] === 'string') {\n targetEndpointUrl = svc['endpoint'] as string;\n break;\n }\n }\n }\n if (targetEndpointUrl) break;\n }\n }\n }\n }\n }\n\n if (!targetEndpointUrl) {\n return this.fail(\n 'No MCP servers.json found.',\n 'MCP server URL responds to JSON-RPC initialize request',\n 'No servers.json',\n {\n priority: 'high',\n description: McpEndpointAudit.meta.description,\n code: McpEndpointAudit.meta.guidance?.code,\n },\n );\n }\n\n const url = targetEndpointUrl;\n\n try {\n const jsonRpcBody = JSON.stringify({\n jsonrpc: '2.0',\n id: 1,\n method: 'initialize',\n params: {\n protocolVersion: '2024-11-05',\n capabilities: {},\n clientInfo: { name: 'ucp-scanner', version: '1.0.0' },\n },\n });\n\n const response = await ctx.fetch({\n url,\n method: 'POST',\n body: jsonRpcBody,\n contentType: 'application/json',\n });\n\n if (response.status === 200) {\n const respBody = tryParseJson(response.body);\n if (\n isObject(respBody) &&\n respBody['jsonrpc'] === '2.0' &&\n !('error' in respBody) &&\n isObject(respBody['result']) &&\n typeof (respBody['result'] as Record<string, unknown>)['protocolVersion'] === 'string'\n ) {\n return this.pass(\n `MCP endpoint at ${url} responded with valid JSON-RPC initialize result.`,\n 'MCP server URL responds to JSON-RPC initialize request',\n `${url} -> HTTP 200, valid JSON-RPC response`,\n );\n }\n return this.warn(\n `MCP endpoint at ${url} returned HTTP 200 but response is not valid JSON-RPC.`,\n 'MCP server URL responds to JSON-RPC initialize request',\n `${url} -> HTTP 200, non-JSON-RPC response`,\n {\n priority: 'high',\n description: McpEndpointAudit.meta.description,\n code: `// Expected request:\\nPOST /mcp\\nContent-Type: application/json\\n\\n{\\n \"jsonrpc\": \"2.0\",\\n \"id\": 1,\\n \"method\": \"initialize\",\\n \"params\": {\\n \"protocolVersion\": \"2024-11-05\",\\n \"capabilities\": {},\\n \"clientInfo\": { \"name\": \"test\", \"version\": \"1.0.0\" }\\n }\\n}\\n\\n// Expected response:\\n{\\n \"jsonrpc\": \"2.0\",\\n \"id\": 1,\\n \"result\": {\\n \"protocolVersion\": \"2024-11-05\",\\n \"serverInfo\": { \"name\": \"your-server\", \"version\": \"1.0.0\" },\\n \"capabilities\": { \"tools\": {} }\\n }\\n}`,\n },\n );\n }\n\n return this.fail(\n `MCP endpoint at ${url} returned HTTP ${response.status}.`,\n 'MCP server URL responds to JSON-RPC initialize request',\n `${url} -> HTTP ${response.status}`,\n {\n priority: 'high',\n description: McpEndpointAudit.meta.description,\n code: `// Expected request:\\nPOST /mcp\\nContent-Type: application/json\\n\\n{\\n \"jsonrpc\": \"2.0\",\\n \"id\": 1,\\n \"method\": \"initialize\",\\n \"params\": {\\n \"protocolVersion\": \"2024-11-05\",\\n \"capabilities\": {},\\n \"clientInfo\": { \"name\": \"test\", \"version\": \"1.0.0\" }\\n }\\n}\\n\\n// Expected response:\\n{\\n \"jsonrpc\": \"2.0\",\\n \"id\": 1,\\n \"result\": {\\n \"protocolVersion\": \"2024-11-05\",\\n \"serverInfo\": { \"name\": \"your-server\", \"version\": \"1.0.0\" },\\n \"capabilities\": { \"tools\": {} }\\n }\\n}`,\n },\n );\n } catch {\n return this.fail(\n `MCP endpoint at ${url} is not reachable.`,\n 'MCP server URL responds to JSON-RPC initialize request',\n `${url} -> unreachable`,\n {\n priority: 'high',\n description: McpEndpointAudit.meta.description,\n code: `// Expected request:\\nPOST /mcp\\nContent-Type: application/json\\n\\n{\\n \"jsonrpc\": \"2.0\",\\n \"id\": 1,\\n \"method\": \"initialize\",\\n \"params\": {\\n \"protocolVersion\": \"2024-11-05\",\\n \"capabilities\": {},\\n \"clientInfo\": { \"name\": \"test\", \"version\": \"1.0.0\" }\\n }\\n}\\n\\n// Expected response:\\n{\\n \"jsonrpc\": \"2.0\",\\n \"id\": 1,\\n \"result\": {\\n \"protocolVersion\": \"2024-11-05\",\\n \"serverInfo\": { \"name\": \"your-server\", \"version\": \"1.0.0\" },\\n \"capabilities\": { \"tools\": {} }\\n }\\n}`,\n },\n );\n }\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nfunction tryParseJson(body: string): unknown {\n try {\n return JSON.parse(body);\n } catch {\n return undefined;\n }\n}\n\nfunction isObject(val: unknown): val is Record<string, unknown> {\n return typeof val === 'object' && val !== null && !Array.isArray(val);\n}\n\nexport class McpCapabilitiesAudit extends Audit {\n static override meta: AuditMeta = {\n id: '5.14',\n category: 'agent-tools',\n title: 'MCP server advertises capabilities',\n failureTitle: 'MCP server advertises capabilities',\n description:\n 'Without declared capabilities, AI agents do not know whether your MCP server offers tools, resources, or prompts. Declaring capabilities upfront lets agents decide if your server is relevant before connecting, saving time and reducing unnecessary requests.',\n scoreDisplayMode: 'binary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'Without declared capabilities, AI agents cannot determine whether your MCP server offers tools, resources, or prompts. They must attempt connections and probe blindly, wasting time and often skipping your server entirely.',\n fix: 'Add a capabilities object to each server entry in your servers.json, declaring which capability types (tools, resources, prompts) your server supports.',\n code: `{\n \"servers\": [\n {\n \"name\": \"Your Site MCP\",\n \"url\": \"https://yoursite.com/mcp\",\n \"capabilities\": {\n \"tools\": true,\n \"resources\": true,\n \"prompts\": false\n }\n }\n ]\n}`,\n effort: 'trivial',\n docsUrl:\n 'https://modelcontextprotocol.io/specification/2025-03-26/basic/lifecycle#capabilities',\n tags: ['mcp', 'capabilities', 'agent-protocol'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const result = ctx.rootFiles['/.well-known/mcp/servers.json'];\n const ucpResult = ctx.rootFiles['/.well-known/ucp'];\n\n if (result && result.status === 200 && result.body) {\n const parsed = tryParseJson(result.body);\n if (!isObject(parsed) || !Array.isArray(parsed['servers'])) {\n return this.fail(\n 'servers.json has no servers array.',\n 'servers.json or MCP response declares tools, resources, or prompts',\n 'No servers array',\n {\n priority: 'medium',\n description: McpCapabilitiesAudit.meta.description,\n code: McpCapabilitiesAudit.meta.guidance?.code,\n },\n );\n }\n\n const servers = parsed['servers'] as unknown[];\n const capabilityKeys = ['tools', 'resources', 'prompts'];\n const foundCapabilities: string[] = [];\n\n for (const server of servers) {\n if (!isObject(server)) continue;\n for (const key of capabilityKeys) {\n if (server[key] !== undefined && server[key] !== false) {\n foundCapabilities.push(key);\n }\n }\n const caps = server['capabilities'];\n if (isObject(caps)) {\n for (const key of capabilityKeys) {\n if (caps[key] !== undefined && caps[key] !== false && !foundCapabilities.includes(key)) {\n foundCapabilities.push(key);\n }\n }\n }\n }\n\n if (foundCapabilities.length === 0) {\n return this.fail(\n 'No MCP capabilities (tools, resources, prompts) declared in servers.json.',\n 'servers.json or MCP response declares tools, resources, or prompts',\n 'No capabilities declared',\n {\n priority: 'medium',\n description: McpCapabilitiesAudit.meta.description,\n code: McpCapabilitiesAudit.meta.guidance?.code,\n },\n );\n }\n\n const unique = [...new Set(foundCapabilities)];\n return this.pass(\n `MCP server(s) advertise capabilities: ${unique.join(', ')}.`,\n 'servers.json or MCP response declares tools, resources, or prompts',\n unique.join(', '),\n );\n }\n\n if (ucpResult && ucpResult.status === 200 && ucpResult.body) {\n const ucpParsed = tryParseJson(ucpResult.body);\n if (isObject(ucpParsed)) {\n const ucpObj = (ucpParsed['ucp'] ?? ucpParsed) as Record<string, unknown>;\n const capabilities = (ucpParsed['capabilities'] || ucpObj['capabilities']) as Record<string, unknown> | undefined;\n if (capabilities && isObject(capabilities)) {\n const capNames = Object.keys(capabilities).map((cap) => cap.split('.').pop() || cap);\n if (capNames.length > 0) {\n const unique = [...new Set(capNames)];\n return this.pass(\n `Universal Commerce Protocol (UCP/MCP) advertises capabilities: ${unique.join(', ')}.`,\n 'servers.json or MCP response declares tools, resources, or prompts',\n unique.join(', '),\n );\n }\n }\n }\n }\n\n return this.fail(\n 'No MCP servers.json found.',\n 'servers.json or MCP response declares tools, resources, or prompts',\n 'No servers.json',\n {\n priority: 'medium',\n description: McpCapabilitiesAudit.meta.description,\n code: McpCapabilitiesAudit.meta.guidance?.code,\n },\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\nimport { extractForms } from '../../parser';\n\nfunction tryParseJson(body: string): unknown {\n try {\n return JSON.parse(body);\n } catch {\n return undefined;\n }\n}\n\nfunction isObject(val: unknown): val is Record<string, unknown> {\n return typeof val === 'object' && val !== null && !Array.isArray(val);\n}\n\ntype OpenApiPaths = Record<string, Record<string, unknown>>;\ntype OpenApiOperation = Record<string, unknown>;\n\nconst HTTP_METHODS = ['get', 'post', 'put', 'patch', 'delete', 'options', 'head', 'trace'];\n\nfunction getOpenApiSpec(ctx: {\n rootFiles: Record<string, { status: number; body: string }>;\n}): Record<string, unknown> | undefined {\n const jsonResult = ctx.rootFiles['/openapi.json'];\n if (jsonResult && jsonResult.status === 200 && jsonResult.body) {\n const parsed = tryParseJson(jsonResult.body);\n if (isObject(parsed)) return parsed;\n }\n return undefined;\n}\n\nfunction getOperations(\n spec: Record<string, unknown>,\n): Array<{ path: string; method: string; op: OpenApiOperation }> {\n const paths = spec['paths'] as OpenApiPaths | undefined;\n if (!isObject(paths)) return [];\n\n const ops: Array<{ path: string; method: string; op: OpenApiOperation }> = [];\n for (const [path, pathItem] of Object.entries(paths)) {\n if (!isObject(pathItem)) continue;\n for (const method of HTTP_METHODS) {\n const op = pathItem[method];\n if (isObject(op)) {\n ops.push({ path, method, op: op as OpenApiOperation });\n }\n }\n }\n return ops;\n}\n\nconst CONTACT_INDICATORS = [\n 'contact',\n 'inquiry',\n 'enquiry',\n 'lead',\n 'get-in-touch',\n 'getintouch',\n 'reach-out',\n 'message',\n 'feedback',\n 'support',\n];\n\nexport class ContactFormAudit extends Audit {\n static override meta: AuditMeta = {\n id: '5.15',\n category: 'agent-tools',\n title: 'Contact/lead form endpoint',\n failureTitle: 'Contact/lead form endpoint',\n description:\n 'AI agents increasingly handle tasks like \"contact this company for a quote\" on behalf of users. Without a machine-submittable contact form, agents cannot complete these requests, sending users to competitors who have one. Provide an HTML form or an API endpoint.',\n scoreDisplayMode: 'binary',\n weight: 1.0,\n defaultPriority: 'high',\n guidance: {\n impact:\n 'When users ask AI agents to \"contact this company for a quote\" or \"send a message to their support team,\" the agent needs a machine-submittable form or API endpoint. Without one, the agent cannot complete the request and users turn to competitors.',\n fix: 'Add an HTML <form> with a standard action and method attribute for contact/inquiry submission, or expose a POST endpoint in your OpenAPI spec for contact requests.',\n code: `<!-- HTML form approach -->\n<form action=\"/api/contact\" method=\"POST\">\n <input type=\"text\" name=\"name\" placeholder=\"Name\" required />\n <input type=\"email\" name=\"email\" placeholder=\"Email\" required />\n <textarea name=\"message\" placeholder=\"Message\" required></textarea>\n <button type=\"submit\">Send</button>\n</form>\n\n<!-- Or OpenAPI approach -->\n\"paths\": {\n \"/api/contact\": {\n \"post\": {\n \"operationId\": \"submitContact\",\n \"summary\": \"Submit a contact inquiry\"\n }\n }\n}`,\n effort: 'moderate',\n tags: ['forms', 'contact', 'lead-generation'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n // Check pages for forms with contact indicators\n for (const page of ctx.pages) {\n const forms = extractForms(page.$);\n for (const form of forms) {\n const formStr = JSON.stringify(form).toLowerCase();\n const matchedIndicator = CONTACT_INDICATORS.find((ind) => formStr.includes(ind));\n if (matchedIndicator) {\n return this.pass(\n `Contact/lead form found on ${page.url} (indicator: \"${matchedIndicator}\").`,\n 'Page has a contact/inquiry form or OpenAPI has a POST contact endpoint',\n `Form with \"${matchedIndicator}\" on ${page.url}`,\n page.url,\n );\n }\n }\n }\n\n // Check OpenAPI for POST endpoints with contact-like paths\n const spec = getOpenApiSpec(ctx);\n if (spec) {\n const ops = getOperations(spec);\n for (const { path, method } of ops) {\n if (method === 'post') {\n const pathLower = path.toLowerCase();\n const matchedIndicator = CONTACT_INDICATORS.find((ind) => pathLower.includes(ind));\n if (matchedIndicator) {\n return this.pass(\n `OpenAPI has POST endpoint \"${path}\" matching contact indicator \"${matchedIndicator}\".`,\n 'Page has a contact/inquiry form or OpenAPI has a POST contact endpoint',\n `POST ${path}`,\n );\n }\n }\n }\n }\n\n return this.fail(\n 'No contact/lead form or POST contact endpoint found.',\n 'Page has a contact/inquiry form or OpenAPI has a POST contact endpoint',\n 'No contact form detected',\n {\n priority: 'high',\n description: ContactFormAudit.meta.description,\n code: `<!-- HTML form approach -->\\n<form action=\"/api/contact\" method=\"POST\">\\n <input type=\"text\" name=\"name\" placeholder=\"Name\" required />\\n <input type=\"email\" name=\"email\" placeholder=\"Email\" required />\\n <textarea name=\"message\" placeholder=\"Message\" required></textarea>\\n <button type=\"submit\">Send</button>\\n</form>\\n\\n<!-- Or OpenAPI approach -->\\n\"paths\": {\\n \"/api/contact\": {\\n \"post\": {\\n \"operationId\": \"submitContact\",\\n \"summary\": \"Submit a contact inquiry\"\\n }\\n }\\n}`,\n },\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nfunction tryParseJson(body: string): unknown {\n try {\n return JSON.parse(body);\n } catch {\n return undefined;\n }\n}\n\nfunction isObject(val: unknown): val is Record<string, unknown> {\n return typeof val === 'object' && val !== null && !Array.isArray(val);\n}\n\ntype OpenApiPaths = Record<string, Record<string, unknown>>;\ntype OpenApiOperation = Record<string, unknown>;\n\nconst HTTP_METHODS = ['get', 'post', 'put', 'patch', 'delete', 'options', 'head', 'trace'];\n\nfunction getOpenApiSpec(ctx: {\n rootFiles: Record<string, { status: number; body: string }>;\n}): Record<string, unknown> | undefined {\n const jsonResult = ctx.rootFiles['/openapi.json'];\n if (jsonResult && jsonResult.status === 200 && jsonResult.body) {\n const parsed = tryParseJson(jsonResult.body);\n if (isObject(parsed)) return parsed;\n }\n return undefined;\n}\n\nfunction getOperations(\n spec: Record<string, unknown>,\n): Array<{ path: string; method: string; op: OpenApiOperation }> {\n const paths = spec['paths'] as OpenApiPaths | undefined;\n if (!isObject(paths)) return [];\n\n const ops: Array<{ path: string; method: string; op: OpenApiOperation }> = [];\n for (const [path, pathItem] of Object.entries(paths)) {\n if (!isObject(pathItem)) continue;\n for (const method of HTTP_METHODS) {\n const op = pathItem[method];\n if (isObject(op)) {\n ops.push({ path, method, op: op as OpenApiOperation });\n }\n }\n }\n return ops;\n}\n\nfunction findSearchActionUrl(obj: unknown): string | undefined {\n if (!isObject(obj)) return undefined;\n\n // Direct match\n if (\n (obj['@type'] === 'SearchAction' || obj['@type'] === 'WebSite') &&\n isObject(obj['potentialAction'])\n ) {\n const action = obj['potentialAction'] as Record<string, unknown>;\n if (action['@type'] === 'SearchAction' && isObject(action['target'])) {\n const target = action['target'] as Record<string, unknown>;\n if (typeof target['urlTemplate'] === 'string') return target['urlTemplate'];\n }\n if (action['@type'] === 'SearchAction' && typeof action['target'] === 'string') {\n return action['target'];\n }\n }\n\n // Check potentialAction directly\n if (obj['@type'] === 'SearchAction') {\n if (isObject(obj['target'])) {\n const target = obj['target'] as Record<string, unknown>;\n if (typeof target['urlTemplate'] === 'string') return target['urlTemplate'];\n }\n if (typeof obj['target'] === 'string') return obj['target'];\n }\n\n // Recurse into @graph\n if (Array.isArray(obj['@graph'])) {\n for (const item of obj['@graph']) {\n const url = findSearchActionUrl(item);\n if (url) return url;\n }\n }\n\n return undefined;\n}\n\nexport class SearchEndpointAudit extends Audit {\n static override meta: AuditMeta = {\n id: '5.16',\n category: 'agent-tools',\n title: 'Search endpoint functional',\n failureTitle: 'Search endpoint functional',\n description:\n 'A search endpoint lets AI agents find specific content on your site without crawling every page. When a user asks an agent \"find pricing info on Example.com,\" the agent can use your search API directly. Add a Schema.org SearchAction or an OpenAPI search endpoint.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'Without a search endpoint, AI agents must crawl every page to find specific content. When a user asks \"find pricing info on Example.com,\" the agent has no efficient way to locate it, resulting in slow or failed responses.',\n fix: 'Add a Schema.org SearchAction to your homepage JSON-LD, or expose a GET search endpoint in your OpenAPI spec. Ensure the endpoint returns results for a test query.',\n code: `<!-- Schema.org SearchAction in JSON-LD -->\n<script type=\"application/ld+json\">\n{\n \"@context\": \"https://schema.org\",\n \"@type\": \"WebSite\",\n \"url\": \"https://yoursite.com\",\n \"potentialAction\": {\n \"@type\": \"SearchAction\",\n \"target\": {\n \"@type\": \"EntryPoint\",\n \"urlTemplate\": \"https://yoursite.com/search?q={search_term_string}\"\n },\n \"query-input\": \"required name=search_term_string\"\n }\n}\n</script>`,\n effort: 'moderate',\n docsUrl: 'https://schema.org/SearchAction',\n tags: ['search', 'schema-org', 'openapi', 'api'],\n },\n };\n\n async audit(ctx: CheckContext): Promise<AuditResult> {\n // Check JSON-LD for WebSite SearchAction\n for (const page of ctx.pages) {\n for (const ld of page.jsonLd) {\n const searchUrl = findSearchActionUrl(ld);\n if (searchUrl) {\n // Try to verify the search endpoint by substituting a test query\n const testUrl = searchUrl.replace(/\\{[^}]*\\}/, 'test');\n try {\n const result = await ctx.fetch({ url: testUrl });\n if (result.status === 200) {\n return this.pass(\n `SearchAction endpoint is functional: ${testUrl} returned HTTP 200.`,\n 'WebSite SearchAction URL works or OpenAPI has a search GET endpoint',\n `SearchAction URL: ${searchUrl} -> HTTP 200`,\n page.url,\n );\n }\n return this.warn(\n `SearchAction URL found but returned HTTP ${result.status}.`,\n 'WebSite SearchAction URL works or OpenAPI has a search GET endpoint',\n `SearchAction URL: ${searchUrl} -> HTTP ${result.status}`,\n {\n priority: 'medium',\n description: SearchEndpointAudit.meta.description,\n code: `<!-- Schema.org SearchAction in JSON-LD -->\\n<script type=\"application/ld+json\">\\n{\\n \"@context\": \"https://schema.org\",\\n \"@type\": \"WebSite\",\\n \"url\": \"https://yoursite.com\",\\n \"potentialAction\": {\\n \"@type\": \"SearchAction\",\\n \"target\": {\\n \"@type\": \"EntryPoint\",\\n \"urlTemplate\": \"https://yoursite.com/search?q={search_term_string}\"\\n },\\n \"query-input\": \"required name=search_term_string\"\\n }\\n}\\n</script>`,\n },\n page.url,\n );\n } catch {\n return this.warn(\n `SearchAction URL found but could not be reached: ${searchUrl}.`,\n 'WebSite SearchAction URL works or OpenAPI has a search GET endpoint',\n `SearchAction URL: ${searchUrl} -> unreachable`,\n {\n priority: 'medium',\n description: SearchEndpointAudit.meta.description,\n code: `<!-- Schema.org SearchAction in JSON-LD -->\\n<script type=\"application/ld+json\">\\n{\\n \"@context\": \"https://schema.org\",\\n \"@type\": \"WebSite\",\\n \"url\": \"https://yoursite.com\",\\n \"potentialAction\": {\\n \"@type\": \"SearchAction\",\\n \"target\": {\\n \"@type\": \"EntryPoint\",\\n \"urlTemplate\": \"https://yoursite.com/search?q={search_term_string}\"\\n },\\n \"query-input\": \"required name=search_term_string\"\\n }\\n}\\n</script>`,\n },\n page.url,\n );\n }\n }\n }\n }\n\n // Check OpenAPI for search-like GET endpoints\n const spec = getOpenApiSpec(ctx);\n if (spec) {\n const ops = getOperations(spec);\n for (const { path, method } of ops) {\n if (method === 'get' && path.toLowerCase().includes('search')) {\n return this.pass(\n `OpenAPI has GET search endpoint: ${path}.`,\n 'WebSite SearchAction URL works or OpenAPI has a search GET endpoint',\n `GET ${path}`,\n );\n }\n }\n }\n\n return this.fail(\n 'No functional search endpoint found (no SearchAction or OpenAPI search GET).',\n 'WebSite SearchAction URL works or OpenAPI has a search GET endpoint',\n 'No search endpoint detected',\n {\n priority: 'medium',\n description: SearchEndpointAudit.meta.description,\n code: `<!-- Schema.org SearchAction in JSON-LD -->\\n<script type=\"application/ld+json\">\\n{\\n \"@context\": \"https://schema.org\",\\n \"@type\": \"WebSite\",\\n \"url\": \"https://yoursite.com\",\\n \"potentialAction\": {\\n \"@type\": \"SearchAction\",\\n \"target\": {\\n \"@type\": \"EntryPoint\",\\n \"urlTemplate\": \"https://yoursite.com/search?q={search_term_string}\"\\n },\\n \"query-input\": \"required name=search_term_string\"\\n }\\n}\\n</script>`,\n },\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class DataActionCtasAudit extends Audit {\n static override meta: AuditMeta = {\n id: '5.17',\n category: 'agent-tools',\n title: 'data-action attributes on CTAs',\n failureTitle: 'data-action attributes on CTAs',\n description:\n 'data-action attributes help AI browser agents (like ChatGPT Browse and Google Mariner) identify clickable CTAs and understand what each button does. Without these hints, agents must guess which elements are interactive based on text alone.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'low',\n guidance: {\n impact:\n 'Without data-action attributes, AI browser agents like ChatGPT Browse and Google Mariner must guess which elements are clickable and what they do. This leads to missed conversions when agents cannot reliably identify your \"Book a Demo\" or \"Add to Cart\" buttons.',\n fix: 'Add data-action, data-action-type, and data-action-label attributes to your key CTA buttons and links. Use descriptive action names and categorize them (e.g., \"conversion\", \"navigation\").',\n code: `<button data-action=\"book-demo\" data-action-type=\"conversion\"\n data-action-label=\"Book a Demo\">\n Book a Demo\n</button>\n\n<a href=\"/pricing\" data-action=\"view-pricing\" data-action-type=\"navigation\"\n data-action-label=\"See Pricing\">\n See Pricing\n</a>`,\n effort: 'easy',\n tags: ['html', 'cta', 'browser-agent', 'accessibility'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n let totalDataAction = 0;\n let totalDataActionType = 0;\n let foundPage = '';\n\n for (const page of ctx.pages) {\n const withDataAction = page.$('[data-action]');\n const withDataActionType = page.$('[data-action-type]');\n\n if (withDataAction.length > 0 || withDataActionType.length > 0) {\n totalDataAction += withDataAction.length;\n totalDataActionType += withDataActionType.length;\n if (!foundPage) foundPage = page.url;\n }\n }\n\n if (totalDataAction > 0 && totalDataActionType > 0) {\n return this.pass(\n `Found ${totalDataAction} element(s) with data-action and ${totalDataActionType} with data-action-type.`,\n 'Elements with data-action and data-action-type attributes',\n `${totalDataAction} data-action, ${totalDataActionType} data-action-type`,\n foundPage,\n );\n }\n\n if (totalDataAction > 0 || totalDataActionType > 0) {\n return this.warn(\n `Partial data-action markup: ${totalDataAction} data-action, ${totalDataActionType} data-action-type.`,\n 'Elements with data-action and data-action-type attributes',\n `${totalDataAction} data-action, ${totalDataActionType} data-action-type`,\n {\n priority: 'low',\n description: DataActionCtasAudit.meta.description,\n code: `<button data-action=\"book-demo\" data-action-type=\"conversion\"\\n data-action-label=\"Book a Demo\">\\n Book a Demo\\n</button>\\n\\n<a href=\"/pricing\" data-action=\"view-pricing\" data-action-type=\"navigation\"\\n data-action-label=\"See Pricing\">\\n See Pricing\\n</a>`,\n },\n foundPage,\n );\n }\n\n return this.fail(\n 'No elements with data-action or data-action-type attributes found.',\n 'Elements with data-action and data-action-type attributes',\n 'None',\n {\n priority: 'low',\n description: DataActionCtasAudit.meta.description,\n code: `<button data-action=\"book-demo\" data-action-type=\"conversion\"\\n data-action-label=\"Book a Demo\">\\n Book a Demo\\n</button>\\n\\n<a href=\"/pricing\" data-action=\"view-pricing\" data-action-type=\"navigation\"\\n data-action-label=\"See Pricing\">\\n See Pricing\\n</a>`,\n },\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nconst CAPTCHA_PATTERNS = [\n 'recaptcha',\n 'hcaptcha',\n 'turnstile',\n 'google.com/recaptcha',\n 'hcaptcha.com',\n 'challenges.cloudflare.com/turnstile',\n];\n\nexport class NoBlockingCaptchaAudit extends Audit {\n static override meta: AuditMeta = {\n id: '5.18',\n category: 'agent-tools',\n title: \"Forms don't use blocking CAPTCHA\",\n failureTitle: \"Forms don't use blocking CAPTCHA\",\n description:\n 'Blocking CAPTCHAs like reCAPTCHA and hCaptcha prevent AI agents from completing forms on behalf of users. When someone asks an AI assistant to \"fill out the contact form on Example.com,\" the CAPTCHA blocks the action entirely. Use honeypot fields or invisible server-side validation instead.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'high',\n guidance: {\n impact:\n 'Blocking CAPTCHAs completely prevent AI agents from submitting forms on behalf of users. When a user asks an agent to \"fill out the contact form,\" the CAPTCHA blocks the action entirely, forcing the user to do it manually or go to a competitor.',\n fix: 'Replace visible CAPTCHAs (reCAPTCHA, hCaptcha, Turnstile) with invisible bot-detection methods such as honeypot fields, server-side rate limiting, or invisible reCAPTCHA v3 score-based checks that do not require user interaction.',\n code: `<!-- Replace CAPTCHA with a honeypot field -->\n<form action=\"/api/contact\" method=\"POST\">\n <!-- Hidden honeypot field - bots fill this, humans don't -->\n <input type=\"text\" name=\"website_url\" style=\"display:none\"\n tabindex=\"-1\" autocomplete=\"off\" />\n\n <input type=\"text\" name=\"name\" required />\n <input type=\"email\" name=\"email\" required />\n <textarea name=\"message\" required></textarea>\n <button type=\"submit\">Send</button>\n</form>\n\n<!-- Server-side: reject if website_url is filled -->`,\n effort: 'moderate',\n tags: ['forms', 'captcha', 'accessibility', 'bot-detection'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const detectedCaptchas: Array<{ page: string; type: string }> = [];\n\n for (const page of ctx.pages) {\n const html = page.fetchResult.body.toLowerCase();\n for (const pattern of CAPTCHA_PATTERNS) {\n if (html.includes(pattern)) {\n detectedCaptchas.push({ page: page.url, type: pattern });\n }\n }\n }\n\n if (detectedCaptchas.length === 0) {\n return this.pass(\n 'No blocking CAPTCHA scripts detected on scanned pages.',\n 'No recaptcha, hcaptcha, or turnstile script includes detected',\n 'No CAPTCHA detected',\n );\n }\n\n // Deduplicate by type\n const uniqueTypes = [...new Set(detectedCaptchas.map((c) => c.type))];\n\n return this.warn(\n `Blocking CAPTCHA detected: ${uniqueTypes.join(', ')}. This may prevent AI agents from submitting forms.`,\n 'No recaptcha, hcaptcha, or turnstile script includes detected',\n `CAPTCHA: ${uniqueTypes.join(', ')} on ${[...new Set(detectedCaptchas.map((c) => c.page))].join(', ')}`,\n {\n priority: 'high',\n description: NoBlockingCaptchaAudit.meta.description,\n code: `<!-- Replace CAPTCHA with a honeypot field -->\\n<form action=\"/api/contact\" method=\"POST\">\\n <!-- Hidden honeypot field - bots fill this, humans don't -->\\n <input type=\"text\" name=\"website_url\" style=\"display:none\"\\n tabindex=\"-1\" autocomplete=\"off\" />\\n\\n <input type=\"text\" name=\"name\" required />\\n <input type=\"email\" name=\"email\" required />\\n <textarea name=\"message\" required></textarea>\\n <button type=\"submit\">Send</button>\\n</form>\\n\\n<!-- Server-side: reject if website_url is filled -->`,\n },\n detectedCaptchas[0]!.page,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\nimport { extractForms } from '../../parser';\n\nexport class FormsNoJsAudit extends Audit {\n static override meta: AuditMeta = {\n id: '5.19',\n category: 'agent-tools',\n title: 'Forms work without JavaScript',\n failureTitle: 'Forms work without JavaScript',\n description:\n 'Many AI agents do not execute JavaScript, so forms that rely on JS for submission are invisible to them. Adding standard HTML action and method attributes ensures forms work via simple HTTP requests, making them accessible to all AI agents.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'Most AI agents do not execute JavaScript. If your forms rely on JS for submission (e.g., React/Vue event handlers with no HTML action), agents cannot submit them at all. This blocks lead capture, contact requests, and any form-based interaction.',\n fix: 'Ensure every <form> element has a standard HTML action attribute pointing to a server endpoint and a method attribute (typically POST). This allows forms to work via plain HTTP requests without JavaScript.',\n code: `<!-- Use standard HTML form attributes -->\n<form action=\"/api/contact\" method=\"POST\">\n <input type=\"text\" name=\"name\" required />\n <input type=\"email\" name=\"email\" required />\n <textarea name=\"message\" required></textarea>\n <button type=\"submit\">Send</button>\n</form>`,\n effort: 'easy',\n tags: ['forms', 'html', 'accessibility', 'no-js'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n let totalForms = 0;\n let formsWithAction = 0;\n let formsWithMethod = 0;\n let firstPageUrl = '';\n\n for (const page of ctx.pages) {\n const forms = extractForms(page.$);\n totalForms += forms.length;\n\n for (const form of forms) {\n if (form.action && form.action !== '') formsWithAction++;\n /* v8 ignore start */\n if (form.method && form.method !== '') formsWithMethod++;\n if (!firstPageUrl && forms.length > 0) firstPageUrl = page.url;\n /* v8 ignore stop */\n }\n }\n\n if (totalForms === 0) {\n return this.notApplicable(\n 'No forms found on scanned pages — nothing to check.',\n 'Forms have action attribute and method defined',\n '0 forms',\n );\n }\n\n const fullyFunctional = formsWithAction; // action is the critical attribute for no-JS\n const allHaveBoth = formsWithAction === totalForms && formsWithMethod === totalForms;\n\n if (allHaveBoth) {\n return this.pass(\n `All ${totalForms} form(s) have both action and method attributes.`,\n 'Forms have action attribute and method defined',\n `${totalForms}/${totalForms} forms with action and method`,\n firstPageUrl,\n );\n }\n\n const recommendation = {\n priority: 'medium' as const,\n description: FormsNoJsAudit.meta.description,\n code: `<!-- Use standard HTML form attributes -->\\n<form action=\"/api/contact\" method=\"POST\">\\n <input type=\"text\" name=\"name\" required />\\n <input type=\"email\" name=\"email\" required />\\n <textarea name=\"message\" required></textarea>\\n <button type=\"submit\">Send</button>\\n</form>`,\n };\n\n if (fullyFunctional > 0) {\n return this.warn(\n `${formsWithAction}/${totalForms} forms have action, ${formsWithMethod}/${totalForms} have method.`,\n 'Forms have action attribute and method defined',\n `${formsWithAction}/${totalForms} action, ${formsWithMethod}/${totalForms} method`,\n recommendation,\n firstPageUrl,\n );\n }\n\n return this.fail(\n `None of the ${totalForms} form(s) have an action attribute — they require JavaScript to submit.`,\n 'Forms have action attribute and method defined',\n `0/${totalForms} forms with action`,\n recommendation,\n firstPageUrl,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nfunction tryParseJson(body: string): unknown {\n try {\n return JSON.parse(body);\n } catch {\n return undefined;\n }\n}\n\nfunction isObject(val: unknown): val is Record<string, unknown> {\n return typeof val === 'object' && val !== null && !Array.isArray(val);\n}\n\nexport class WebmcpManifestAudit extends Audit {\n static override meta: AuditMeta = {\n id: '5.20',\n category: 'agent-tools',\n title: 'WebMCP discovery manifest',\n failureTitle: 'WebMCP discovery manifest',\n description:\n \"WebMCP is a proposed W3C standard (Chrome 146+) that lets websites expose structured tools to AI agents. A /.well-known/webmcp manifest is an emerging convention (not yet in the formal spec) that enables agentic crawlers to discover your site's capabilities before visiting, similar to how robots.txt works for search engines.\",\n scoreDisplayMode: 'binary',\n weight: 1.0,\n defaultPriority: 'high',\n guidance: {\n impact:\n 'Without a WebMCP manifest, AI agents cannot pre-discover what actions your site supports. Agents must fall back to scraping or vision-based interaction, which is slower, less reliable, and may miss key capabilities like product search or checkout.',\n fix: \"Create a /.well-known/webmcp manifest file describing your site's available tools, their parameters, and capabilities.\",\n code: `// /.well-known/webmcp\n{\n \"name\": \"Your Store\",\n \"description\": \"E-commerce store with product search and checkout\",\n \"tools\": [\n {\n \"name\": \"searchProducts\",\n \"description\": \"Search the product catalog by keyword, category, or filters\",\n \"inputSchema\": {\n \"type\": \"object\",\n \"properties\": {\n \"query\": { \"type\": \"string\", \"description\": \"Search keywords\" },\n \"category\": { \"type\": \"string\", \"description\": \"Product category\" }\n },\n \"required\": [\"query\"]\n }\n }\n ]\n}`,\n effort: 'moderate',\n docsUrl: 'https://webmcp.link/',\n tags: ['webmcp', 'discovery', 'agent-protocol', 'chrome-146'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const result = ctx.rootFiles['/.well-known/webmcp'];\n if (!result || result.status !== 200 || !result.body) {\n return this.fail(\n '/.well-known/webmcp manifest not found.',\n '/.well-known/webmcp returns 200 with valid JSON describing available tools',\n result ? `HTTP ${result.status}` : 'Not fetched',\n 'high',\n );\n }\n\n const parsed = tryParseJson(result.body);\n if (!isObject(parsed)) {\n return this.fail(\n '/.well-known/webmcp is not valid JSON.',\n 'Valid JSON object with tools array',\n 'Invalid JSON',\n 'high',\n );\n }\n\n if (!Array.isArray(parsed['tools'])) {\n return this.fail(\n '/.well-known/webmcp does not contain a tools array.',\n 'JSON object with \"tools\" array',\n 'No tools array found',\n 'high',\n );\n }\n\n const rawTools = parsed['tools'] as unknown[];\n const tools = rawTools.filter(\n (t): t is Record<string, unknown> => isObject(t) && typeof t['name'] === 'string',\n );\n\n if (tools.length === 0) {\n return this.fail(\n rawTools.length === 0\n ? '/.well-known/webmcp has an empty tools array.'\n : `/.well-known/webmcp has ${rawTools.length} entries but none are valid tool objects with a name.`,\n 'At least one tool with a name defined in the manifest',\n `${tools.length} valid tool(s) out of ${rawTools.length} entries`,\n 'high',\n );\n }\n\n return this.pass(\n `WebMCP manifest found with ${tools.length} valid tool(s).`,\n '/.well-known/webmcp returns 200 with valid JSON containing tools array',\n `Valid JSON with ${tools.length} tool(s)`,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class WebmcpDeclarativeFormsAudit extends Audit {\n static override meta: AuditMeta = {\n id: '5.21',\n category: 'agent-tools',\n title: 'WebMCP declarative form tools',\n failureTitle: 'WebMCP declarative form tools',\n description:\n \"WebMCP's Declarative API lets you expose HTML forms as agent-callable tools by adding toolname and tooldescription attributes. AI agents can then discover and invoke these forms without JavaScript, using standard HTML semantics.\",\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'high',\n guidance: {\n impact:\n 'Without WebMCP declarative attributes, AI agents cannot discover your forms as structured tools. They must rely on heuristics or vision to identify interactive elements, leading to unreliable agent interactions.',\n fix: 'Add toolname and tooldescription attributes to your <form> elements to expose them as WebMCP tools.',\n code: `<!-- WebMCP declarative form -->\n<form toolname=\"searchProducts\"\n tooldescription=\"Search the product catalog by keyword\"\n action=\"/search\" method=\"GET\">\n <input type=\"text\" name=\"q\" placeholder=\"Search products...\" />\n <button type=\"submit\">Search</button>\n</form>\n\n<!-- Checkout form -->\n<form toolname=\"addToCart\"\n tooldescription=\"Add a product to the shopping cart\"\n action=\"/cart/add\" method=\"POST\">\n <input type=\"hidden\" name=\"product_id\" />\n <input type=\"number\" name=\"quantity\" value=\"1\" min=\"1\" />\n <button type=\"submit\">Add to Cart</button>\n</form>`,\n effort: 'easy',\n docsUrl: 'https://webmcp.link/',\n tags: ['webmcp', 'declarative', 'forms', 'chrome-146'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n let totalForms = 0;\n let webmcpForms = 0;\n let firstPageUrl = '';\n const toolNames: string[] = [];\n\n for (const page of ctx.pages) {\n const forms = page.$('form');\n forms.each((_, el) => {\n totalForms++;\n const toolname = page.$(el).attr('toolname');\n const tooldescription = page.$(el).attr('tooldescription');\n if (toolname) {\n webmcpForms++;\n toolNames.push(toolname);\n if (!firstPageUrl) firstPageUrl = page.url;\n } else if (tooldescription) {\n // Has description but no name — partial implementation\n webmcpForms++;\n if (!firstPageUrl) firstPageUrl = page.url;\n }\n });\n }\n\n if (totalForms === 0) {\n return this.warn(\n 'No forms found on scanned pages.',\n 'At least one form with toolname and tooldescription attributes',\n '0 forms on scanned pages',\n 'medium',\n );\n }\n\n if (webmcpForms === 0) {\n return this.fail(\n `Found ${totalForms} form(s) but none have WebMCP toolname/tooldescription attributes.`,\n 'Forms have toolname and tooldescription attributes',\n `0/${totalForms} forms with WebMCP attributes`,\n 'high',\n );\n }\n\n const toolsLabel = toolNames.length > 0 ? ` (tools: ${toolNames.join(', ')})` : '';\n\n if (webmcpForms < totalForms) {\n return this.warn(\n `${webmcpForms}/${totalForms} form(s) have WebMCP attributes${toolsLabel}.`,\n 'All forms have toolname and tooldescription attributes',\n `${webmcpForms}/${totalForms} forms with WebMCP attributes`,\n 'medium',\n firstPageUrl,\n );\n }\n\n return this.pass(\n `All ${totalForms} form(s) have WebMCP attributes${toolsLabel}.`,\n 'Forms have toolname and tooldescription attributes',\n `${webmcpForms}/${totalForms} forms with WebMCP attributes`,\n firstPageUrl,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class WebmcpInputQualityAudit extends Audit {\n static override meta: AuditMeta = {\n id: '5.22',\n category: 'agent-tools',\n title: 'WebMCP tool input quality',\n failureTitle: 'WebMCP tool input quality',\n description:\n 'For AI agents to correctly invoke WebMCP tools, form inputs must have descriptive name attributes, appropriate type attributes, and associated labels or descriptions. Poor input quality leads to agents guessing parameter values or skipping the tool entirely.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'AI agents map form inputs to tool parameters. Inputs without meaningful names (e.g., \"field1\"), missing types, or no labels force agents to guess what data to provide, resulting in failed submissions or incorrect values.',\n fix: 'Ensure every input in a WebMCP-declared form has a descriptive name, an appropriate type, and an associated label element or aria-label.',\n code: `<form toolname=\"searchProducts\"\n tooldescription=\"Search products by keyword and filters\">\n <label for=\"search-query\">Search query</label>\n <input id=\"search-query\" type=\"text\" name=\"query\"\n placeholder=\"e.g., red running shoes\" required />\n\n <label for=\"price-max\">Maximum price</label>\n <input id=\"price-max\" type=\"number\" name=\"maxPrice\"\n placeholder=\"100\" min=\"0\" />\n\n <label for=\"category\">Category</label>\n <select id=\"category\" name=\"category\">\n <option value=\"\">All categories</option>\n <option value=\"shoes\">Shoes</option>\n </select>\n</form>`,\n effort: 'easy',\n docsUrl: 'https://webmcp.link/',\n tags: ['webmcp', 'inputs', 'quality', 'chrome-146'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n let webmcpFormCount = 0;\n let totalInputs = 0;\n let inputsWithName = 0;\n let inputsWithLabel = 0;\n let firstPageUrl = '';\n\n for (const page of ctx.pages) {\n page.$('form[toolname]').each((_, formEl) => {\n webmcpFormCount++;\n if (!firstPageUrl) firstPageUrl = page.url;\n\n page\n .$(formEl)\n .find('input, select, textarea')\n .each((_j, inputEl) => {\n const $input = page.$(inputEl);\n const inputType = $input.attr('type') || '';\n // Skip non-data input types\n if (['hidden', 'submit', 'button', 'reset', 'image'].includes(inputType)) return;\n\n totalInputs++;\n const name = $input.attr('name');\n if (name && name.length > 0) inputsWithName++;\n\n // Check for label association\n const id = $input.attr('id');\n const ariaLabel = $input.attr('aria-label');\n const placeholder = $input.attr('placeholder');\n const escapedId = id ? id.replace(/([\"\\\\\\]:])/g, '\\\\$1') : '';\n const hasLabel =\n (escapedId && page.$(`label[for=\"${escapedId}\"]`).length > 0) ||\n (ariaLabel && ariaLabel.length > 0) ||\n (placeholder && placeholder.length > 0);\n if (hasLabel) inputsWithLabel++;\n });\n });\n }\n\n if (webmcpFormCount === 0) {\n return this.notApplicable(\n 'No WebMCP-declared forms found — input quality cannot be assessed.',\n 'WebMCP form inputs have name, type, and label',\n 'No WebMCP forms',\n );\n }\n\n if (totalInputs === 0) {\n return this.warn(\n `Found ${webmcpFormCount} WebMCP form(s) but no visible inputs.`,\n 'WebMCP forms contain labeled inputs',\n '0 visible inputs',\n 'medium',\n firstPageUrl,\n );\n }\n\n const nameRatio = inputsWithName / totalInputs;\n const labelRatio = inputsWithLabel / totalInputs;\n const allGood = nameRatio === 1 && labelRatio >= 0.8;\n\n if (allGood) {\n return this.pass(\n `All ${totalInputs} input(s) across ${webmcpFormCount} WebMCP form(s) have names; ${inputsWithLabel}/${totalInputs} have labels.`,\n 'Inputs have name, type, and label attributes',\n `${inputsWithName}/${totalInputs} named, ${inputsWithLabel}/${totalInputs} labeled`,\n firstPageUrl,\n );\n }\n\n if (nameRatio >= 0.5) {\n return this.warn(\n `${inputsWithName}/${totalInputs} inputs have names, ${inputsWithLabel}/${totalInputs} have labels.`,\n 'All inputs have name and label attributes',\n `${inputsWithName}/${totalInputs} named, ${inputsWithLabel}/${totalInputs} labeled`,\n 'medium',\n firstPageUrl,\n );\n }\n\n return this.fail(\n `Only ${inputsWithName}/${totalInputs} inputs have names in WebMCP forms — agents cannot identify parameters.`,\n 'All inputs have name and label attributes',\n `${inputsWithName}/${totalInputs} named, ${inputsWithLabel}/${totalInputs} labeled`,\n 'medium',\n firstPageUrl,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nfunction isObject(val: unknown): val is Record<string, unknown> {\n return typeof val === 'object' && val !== null && !Array.isArray(val);\n}\n\n/** Coerce an unknown JSON value to a string; non-strings → ''. */\nfunction asString(val: unknown): string {\n return typeof val === 'string' ? val : '';\n}\n\nfunction tryParseJson(body: string): unknown {\n try {\n return JSON.parse(body);\n } catch {\n return undefined;\n }\n}\n\nconst VERB_PATTERN =\n /^(get|search|find|list|add|create|update|remove|delete|submit|check|view|browse|filter|sort|compare|subscribe|unsubscribe|track|cancel|buy|checkout|pay|register|login|signup|contact|send|request|book|reserve|download|export|import|upload|apply|calculate|estimate|validate|verify|reset|set|toggle|select|deselect|clear|save|load|fetch|query|lookup|retrieve|show|display|open|close|start|stop|pause|resume|join|leave|follow|unfollow|like|dislike|share|rate|review|comment|post|reply|forward|archive|pin|unpin|mark|unmark|tag|untag|assign|claim|release|approve|reject|accept|decline|confirm|deny|enable|disable|activate|deactivate|install|uninstall|connect|disconnect)([A-Z]|$)/;\n\nconst MIN_DESCRIPTION_LENGTH = 20;\n\nexport class WebmcpToolNamingAudit extends Audit {\n static override meta: AuditMeta = {\n id: '5.23',\n category: 'agent-tools',\n title: 'WebMCP tool naming conventions',\n failureTitle: 'WebMCP tool naming conventions',\n description:\n \"WebMCP tools should follow verb-based camelCase naming (e.g., searchProducts, addToCart) and have descriptions of at least 20 characters. This helps AI agents understand the tool's purpose and invoke the correct one.\",\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'low',\n guidance: {\n impact:\n 'Poorly named tools (e.g., \"form1\", \"action\") make it harder for AI agents to select the right tool for a user\\'s intent. Agents rely heavily on tool names and descriptions to decide which actions to take.',\n fix: 'Use verb-based camelCase names that describe the action (e.g., searchProducts, addToCart, submitInquiry) and descriptions of at least 20 characters explaining what the tool does.',\n code: `<!-- Good naming -->\n<form toolname=\"searchProducts\"\n tooldescription=\"Search the product catalog by keyword, category, price range, and other filters\">\n ...\n</form>\n\n<!-- Bad naming -->\n<form toolname=\"form1\"\n tooldescription=\"Search\">\n ...\n</form>`,\n effort: 'trivial',\n docsUrl: 'https://webmcp.link/',\n tags: ['webmcp', 'naming', 'best-practices', 'chrome-146'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const seen = new Set<string>();\n const tools: Array<{ name: string; description: string; source: string }> = [];\n\n // Collect from manifest first (canonical source)\n const manifestResult = ctx.rootFiles['/.well-known/webmcp'];\n if (manifestResult?.status === 200 && manifestResult.body) {\n const parsed = tryParseJson(manifestResult.body);\n if (isObject(parsed) && Array.isArray(parsed['tools'])) {\n for (const tool of parsed['tools'] as unknown[]) {\n if (isObject(tool)) {\n const name = asString(tool['name']);\n tools.push({\n name,\n description: asString(tool['description']),\n source: 'manifest',\n });\n if (name) seen.add(name);\n }\n }\n }\n }\n\n // Collect from declarative forms, skip duplicates\n for (const page of ctx.pages) {\n page.$('form[toolname]').each((_, el) => {\n const name = page.$(el).attr('toolname') || '';\n if (name && seen.has(name)) return;\n const desc = page.$(el).attr('tooldescription') || '';\n tools.push({ name, description: desc, source: 'declarative' });\n if (name) seen.add(name);\n });\n }\n\n if (tools.length === 0) {\n return this.notApplicable(\n 'No WebMCP tools found — tool naming cannot be assessed.',\n 'Tool names follow verb-based camelCase with 20+ char descriptions',\n 'No WebMCP tools',\n );\n }\n\n let goodNames = 0;\n let goodDescriptions = 0;\n const badNames: string[] = [];\n const shortDescriptions: string[] = [];\n\n for (const tool of tools) {\n if (VERB_PATTERN.test(tool.name)) {\n goodNames++;\n } else {\n badNames.push(tool.name);\n }\n if (tool.description.length >= MIN_DESCRIPTION_LENGTH) {\n goodDescriptions++;\n } else {\n shortDescriptions.push(tool.name);\n }\n }\n\n const allGood = goodNames === tools.length && goodDescriptions === tools.length;\n\n if (allGood) {\n return this.pass(\n `All ${tools.length} tool(s) follow naming conventions with adequate descriptions.`,\n 'Verb-based camelCase names with 20+ char descriptions',\n `${goodNames}/${tools.length} good names, ${goodDescriptions}/${tools.length} good descriptions`,\n );\n }\n\n const issues: string[] = [];\n if (badNames.length > 0) {\n issues.push(`non-verb names: ${badNames.join(', ')}`);\n }\n if (shortDescriptions.length > 0) {\n issues.push(`short descriptions: ${shortDescriptions.join(', ')}`);\n }\n\n if (goodNames >= tools.length / 2) {\n return this.warn(\n `${goodNames}/${tools.length} tools follow naming conventions. Issues: ${issues.join('; ')}.`,\n 'Verb-based camelCase names with 20+ char descriptions',\n `${goodNames}/${tools.length} good names, ${goodDescriptions}/${tools.length} good descriptions`,\n 'low',\n );\n }\n\n return this.fail(\n `Only ${goodNames}/${tools.length} tools follow naming conventions. Issues: ${issues.join('; ')}.`,\n 'Verb-based camelCase names with 20+ char descriptions',\n `${goodNames}/${tools.length} good names, ${goodDescriptions}/${tools.length} good descriptions`,\n 'low',\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nfunction tryParseJson(body: string): unknown {\n try {\n return JSON.parse(body);\n } catch {\n return undefined;\n }\n}\n\nfunction isObject(val: unknown): val is Record<string, unknown> {\n return typeof val === 'object' && val !== null && !Array.isArray(val);\n}\n\n/** Coerce an unknown JSON value to a string; non-strings → ''. */\nfunction asString(val: unknown): string {\n return typeof val === 'string' ? val : '';\n}\n\n// readOnlyHint is in the WebMCP spec; the rest are from MCP and commonly used together\nconst SAFETY_ANNOTATIONS = ['readOnlyHint', 'destructiveHint', 'idempotentHint', 'openWorldHint'];\n\nexport class WebmcpToolAnnotationsAudit extends Audit {\n static override meta: AuditMeta = {\n id: '5.24',\n category: 'agent-tools',\n title: 'WebMCP tool safety annotations',\n failureTitle: 'WebMCP tool safety annotations',\n description:\n 'WebMCP tools should include the readOnlyHint annotation (defined in the WebMCP spec) and ideally MCP-compatible annotations like destructiveHint and idempotentHint, so AI agents can make informed decisions about when to invoke tools and whether to ask for user confirmation.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'Without safety annotations, AI agents treat all tools equally — a \"delete account\" tool looks the same as a \"search products\" tool. Annotations let agents automatically request user confirmation for destructive actions and freely use read-only tools, improving both safety and user experience.',\n fix: 'Add annotation properties to your WebMCP tool definitions in the manifest or as data attributes on declarative forms.',\n code: `// In /.well-known/webmcp manifest\n{\n \"tools\": [\n {\n \"name\": \"searchProducts\",\n \"description\": \"Search the product catalog\",\n \"annotations\": {\n \"readOnlyHint\": true,\n \"destructiveHint\": false,\n \"idempotentHint\": true\n },\n \"inputSchema\": { ... }\n },\n {\n \"name\": \"addToCart\",\n \"description\": \"Add a product to the cart\",\n \"annotations\": {\n \"readOnlyHint\": false,\n \"destructiveHint\": false,\n \"idempotentHint\": false\n },\n \"inputSchema\": { ... }\n }\n ]\n}\n\n<!-- Or on declarative forms -->\n<form toolname=\"addToCart\"\n tooldescription=\"Add a product to the shopping cart\"\n data-readonly=\"false\"\n data-destructive=\"false\">`,\n effort: 'easy',\n docsUrl: 'https://webmcp.link/',\n tags: ['webmcp', 'annotations', 'safety', 'chrome-146'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n let totalTools = 0;\n let toolsWithAnnotations = 0;\n const annotationsFound: string[] = [];\n const seen = new Set<string>();\n\n // Check manifest tools (canonical source)\n const manifestResult = ctx.rootFiles['/.well-known/webmcp'];\n if (manifestResult?.status === 200 && manifestResult.body) {\n const parsed = tryParseJson(manifestResult.body);\n if (isObject(parsed) && Array.isArray(parsed['tools'])) {\n for (const tool of parsed['tools'] as unknown[]) {\n if (!isObject(tool)) continue;\n const name = asString(tool['name']);\n totalTools++;\n if (name) seen.add(name);\n const annotations = tool['annotations'];\n if (isObject(annotations)) {\n const found = SAFETY_ANNOTATIONS.filter((a) => a in annotations);\n if (found.length > 0) {\n toolsWithAnnotations++;\n for (const f of found) {\n if (!annotationsFound.includes(f)) annotationsFound.push(f);\n }\n }\n }\n }\n }\n }\n\n // Check declarative forms for data-* annotations, skip duplicates\n for (const page of ctx.pages) {\n page.$('form[toolname]').each((_, el) => {\n const $form = page.$(el);\n const name = $form.attr('toolname') || '';\n if (name && seen.has(name)) return;\n totalTools++;\n if (name) seen.add(name);\n const found = SAFETY_ANNOTATIONS.filter((a) => {\n const dataAttr = a.replace(/([A-Z])/g, '-$1').toLowerCase();\n return $form.attr(`data-${dataAttr}`) !== undefined;\n });\n if (found.length > 0) {\n toolsWithAnnotations++;\n for (const f of found) {\n if (!annotationsFound.includes(f)) annotationsFound.push(f);\n }\n }\n });\n }\n\n if (totalTools === 0) {\n return this.notApplicable(\n 'No WebMCP tools found — safety annotations cannot be assessed.',\n 'WebMCP tools include safety annotations',\n 'No WebMCP tools',\n );\n }\n\n if (toolsWithAnnotations === 0) {\n return this.fail(\n `None of the ${totalTools} WebMCP tool(s) include safety annotations.`,\n 'Tools include readOnlyHint, destructiveHint, or idempotentHint annotations',\n `0/${totalTools} tools with annotations`,\n 'medium',\n );\n }\n\n if (toolsWithAnnotations < totalTools) {\n return this.warn(\n `${toolsWithAnnotations}/${totalTools} tool(s) have annotations (${annotationsFound.join(', ')}).`,\n 'All tools include safety annotations',\n `${toolsWithAnnotations}/${totalTools} annotated`,\n 'medium',\n );\n }\n\n return this.pass(\n `All ${totalTools} tool(s) include safety annotations (${annotationsFound.join(', ')}).`,\n 'Tools include safety annotations',\n `${toolsWithAnnotations}/${totalTools} annotated`,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nfunction tryParseJson(body: string): unknown {\n try {\n return JSON.parse(body);\n } catch {\n return undefined;\n }\n}\n\nfunction isObject(val: unknown): val is Record<string, unknown> {\n return typeof val === 'object' && val !== null && !Array.isArray(val);\n}\n\n/** Coerce an unknown JSON value to a string; non-strings → ''. */\nfunction asString(val: unknown): string {\n return typeof val === 'string' ? val : '';\n}\n\ninterface CommerceAction {\n label: string;\n keywords: string[];\n}\n\nconst COMMERCE_ACTIONS: CommerceAction[] = [\n {\n label: 'Product Search',\n keywords: ['search', 'find', 'query', 'browse', 'filter', 'lookup', 'catalog'],\n },\n {\n label: 'Product Detail',\n keywords: ['product', 'detail', 'productdetail', 'getproduct', 'viewproduct', 'viewitem'],\n },\n { label: 'Add to Cart', keywords: ['cart', 'addtocart', 'basket', 'additem'] },\n {\n label: 'Checkout',\n keywords: ['checkout', 'purchase', 'placeorder', 'completepurchase', 'buyproduct'],\n },\n {\n label: 'Account/Auth',\n keywords: ['login', 'register', 'signup', 'signin', 'authenticate', 'createaccount'],\n },\n {\n label: 'Contact/Support',\n keywords: ['contact', 'support', 'inquiry', 'submitinquiry', 'sendmessage', 'helpdesk'],\n },\n];\n\nconst MIN_COVERAGE = 2; // At least 2 commerce actions for a passing score\n\nexport class WebmcpActionCoverageAudit extends Audit {\n static override meta: AuditMeta = {\n id: '5.25',\n category: 'agent-tools',\n title: 'WebMCP commerce action coverage',\n failureTitle: 'WebMCP commerce action coverage',\n description:\n 'For e-commerce sites, WebMCP tools should cover key commerce actions: product search, product detail, add to cart, checkout, and contact/support. Broader action coverage means AI agents can complete more user tasks without falling back to manual browsing.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'AI shopping agents need to complete full purchase journeys — search, view, add to cart, checkout. If your WebMCP tools only cover search but not checkout, agents abandon the flow and users turn to competitors with full coverage.',\n fix: 'Expose WebMCP tools for the key commerce actions: product search, product detail/view, add to cart, checkout/purchase, and contact/support.',\n code: `// /.well-known/webmcp — full commerce coverage\n{\n \"tools\": [\n {\n \"name\": \"searchProducts\",\n \"description\": \"Search the product catalog by keyword, category, or filters\",\n \"annotations\": { \"readOnlyHint\": true },\n \"inputSchema\": {\n \"type\": \"object\",\n \"properties\": {\n \"query\": { \"type\": \"string\" },\n \"category\": { \"type\": \"string\" },\n \"maxPrice\": { \"type\": \"number\" }\n },\n \"required\": [\"query\"]\n }\n },\n {\n \"name\": \"getProductDetails\",\n \"description\": \"Get full details for a specific product by ID or URL\",\n \"annotations\": { \"readOnlyHint\": true },\n \"inputSchema\": {\n \"type\": \"object\",\n \"properties\": { \"productId\": { \"type\": \"string\" } },\n \"required\": [\"productId\"]\n }\n },\n {\n \"name\": \"addToCart\",\n \"description\": \"Add a product to the shopping cart with quantity\",\n \"annotations\": { \"readOnlyHint\": false, \"idempotentHint\": false },\n \"inputSchema\": {\n \"type\": \"object\",\n \"properties\": {\n \"productId\": { \"type\": \"string\" },\n \"quantity\": { \"type\": \"integer\", \"minimum\": 1 }\n },\n \"required\": [\"productId\"]\n }\n },\n {\n \"name\": \"checkout\",\n \"description\": \"Initiate checkout for the current cart\",\n \"annotations\": { \"readOnlyHint\": false, \"confirmationRequired\": true },\n \"inputSchema\": {\n \"type\": \"object\",\n \"properties\": { \"shippingMethod\": { \"type\": \"string\" } }\n }\n }\n ]\n}`,\n effort: 'moderate',\n docsUrl: 'https://webmcp.link/',\n tags: ['webmcp', 'commerce', 'coverage', 'chrome-146'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const toolSignatures: string[] = [];\n const seen = new Set<string>();\n\n // Collect tool names + descriptions from manifest (canonical source)\n const manifestResult = ctx.rootFiles['/.well-known/webmcp'];\n if (manifestResult?.status === 200 && manifestResult.body) {\n const parsed = tryParseJson(manifestResult.body);\n if (isObject(parsed) && Array.isArray(parsed['tools'])) {\n for (const tool of parsed['tools'] as unknown[]) {\n if (isObject(tool)) {\n const name = asString(tool['name']);\n const sig = `${name} ${asString(tool['description'])}`.toLowerCase();\n toolSignatures.push(sig);\n if (name) seen.add(name);\n }\n }\n }\n }\n\n // Collect from declarative forms, skip duplicates\n for (const page of ctx.pages) {\n page.$('form[toolname]').each((_, el) => {\n const name = page.$(el).attr('toolname') || '';\n if (name && seen.has(name)) return;\n const desc = page.$(el).attr('tooldescription') || '';\n const action = page.$(el).attr('action') || '';\n toolSignatures.push(`${name} ${desc} ${action}`.toLowerCase());\n if (name) seen.add(name);\n });\n }\n\n if (toolSignatures.length === 0) {\n return this.notApplicable(\n 'No WebMCP tools found — commerce action coverage cannot be assessed.',\n `At least ${MIN_COVERAGE} commerce actions covered (search, product, cart, checkout, contact)`,\n 'No WebMCP tools',\n );\n }\n\n // Match tools against commerce actions\n const coveredActions: string[] = [];\n const missingActions: string[] = [];\n\n for (const action of COMMERCE_ACTIONS) {\n const matched = toolSignatures.some((sig) =>\n action.keywords.some((kw) => new RegExp(`\\\\b${kw}\\\\b`).test(sig)),\n );\n if (matched) {\n coveredActions.push(action.label);\n } else {\n missingActions.push(action.label);\n }\n }\n\n const coverage = coveredActions.length;\n const total = COMMERCE_ACTIONS.length;\n\n if (coverage >= 4) {\n return this.pass(\n `${coverage}/${total} commerce actions covered: ${coveredActions.join(', ')}.`,\n `At least ${MIN_COVERAGE} commerce actions covered`,\n `${coverage}/${total} covered`,\n );\n }\n\n if (coverage >= MIN_COVERAGE) {\n return this.warn(\n `${coverage}/${total} commerce actions covered: ${coveredActions.join(', ')}. Missing: ${missingActions.join(', ')}.`,\n `At least 4 commerce actions covered for strong agent support`,\n `${coverage}/${total} covered`,\n 'medium',\n );\n }\n\n return this.fail(\n `Only ${coverage}/${total} commerce actions covered: ${coveredActions.length > 0 ? coveredActions.join(', ') : 'none'}. Missing: ${missingActions.join(', ')}.`,\n `At least ${MIN_COVERAGE} commerce actions covered`,\n `${coverage}/${total} covered`,\n 'medium',\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class SingleH1Audit extends Audit {\n static override meta: AuditMeta = {\n id: '6.1',\n category: 'semantic-html',\n title: 'Single h1 per page',\n failureTitle: 'Single h1 per page',\n description:\n 'AI agents use the single <h1> as the authoritative title of the page for content indexing and answer generation. Ensure exactly one <h1> per page.',\n scoreDisplayMode: 'binary',\n weight: 1.0,\n defaultPriority: 'high',\n guidance: {\n impact:\n \"AI agents use the single <h1> as the authoritative page title for content indexing and answer generation. Multiple <h1> elements create ambiguity about the page's primary topic, causing agents to misidentify or conflate subjects when generating answers.\",\n fix: \"Ensure every page has exactly one <h1> element that clearly describes the page's primary topic. Use h2-h6 for all other headings. If your CMS or template generates multiple <h1> elements, change the extras to the appropriate lower heading level.\",\n code: '<h1>Your Primary Page Title</h1>\\n<h2>First Section</h2>\\n<h2>Second Section</h2>',\n effort: 'trivial',\n docsUrl: 'https://developer.mozilla.org/en-US/docs/Web/HTML/Element/Heading_Elements',\n tags: ['headings', 'h1', 'structure', 'semantic'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const homepage = ctx.pages[0];\n if (!homepage) {\n return this.fail(\n 'No pages available to check.',\n 'Exactly one <h1> on the homepage',\n 'No pages scanned',\n {\n priority: 'high',\n description:\n 'AI agents use the single <h1> as the authoritative title of the page for content indexing and answer generation. Ensure exactly one <h1> per page.',\n code: '<h1>Primary Page Topic</h1>',\n },\n );\n }\n\n const $ = homepage.$;\n const h1Count = $('h1').length;\n const pass = h1Count === 1;\n\n if (pass) {\n return this.pass(\n 'Homepage has exactly one <h1> element.',\n 'Exactly one <h1> on the homepage',\n `${h1Count} <h1> element(s)`,\n homepage.url,\n );\n }\n\n return this.fail(\n `Homepage has ${h1Count} <h1> element(s); expected exactly 1.`,\n 'Exactly one <h1> on the homepage',\n `${h1Count} <h1> element(s)`,\n {\n priority: 'high',\n description:\n \"AI agents use the single <h1> as the authoritative title of the page. Multiple <h1> elements create ambiguity about the page's primary topic, causing agents to misidentify or conflate subjects when generating answers. Ensure exactly one <h1> per page.\",\n code: '<h1>Primary Page Topic</h1>',\n },\n homepage.url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\nimport { extractHeadings } from '../../parser';\n\nexport class SequentialHeadingsAudit extends Audit {\n static override meta: AuditMeta = {\n id: '6.2',\n category: 'semantic-html',\n title: 'Sequential heading hierarchy',\n failureTitle: 'Sequential heading hierarchy',\n description:\n 'AI systems build content outlines from headings to understand document structure. Skipped levels (e.g., h1 to h3 without h2) break the hierarchy, causing agents to misinterpret section nesting and produce inaccurate content summaries. Fix heading levels to follow a sequential order.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'high',\n guidance: {\n impact:\n 'AI systems build content outlines from heading levels to understand document hierarchy. Skipped levels (e.g., h1 directly to h3) break this hierarchy, causing agents to misinterpret section nesting and produce inaccurate content summaries with wrong parent-child relationships.',\n fix: 'Ensure headings follow a sequential order without skipping levels. After an h1, use h2 for major sections, h3 for subsections within h2, and so on. Never jump from h1 to h3 or h2 to h4 without the intermediate level.',\n code: '<h1>Page Title</h1>\\n <h2>Major Section</h2>\\n <h3>Subsection</h3>\\n <h3>Another Subsection</h3>\\n <h2>Another Major Section</h2>',\n effort: 'easy',\n docsUrl: 'https://developer.mozilla.org/en-US/docs/Web/HTML/Element/Heading_Elements',\n tags: ['headings', 'hierarchy', 'structure', 'semantic'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n let pagesWithSkips = 0;\n const totalPages = ctx.pages.length;\n const skipDetails: string[] = [];\n\n // Check if any page has at least 2 headings to evaluate\n let hasEnoughHeadings = false;\n\n for (const page of ctx.pages) {\n const headings = extractHeadings(page.$);\n if (headings.length >= 2) hasEnoughHeadings = true;\n let hasSkip = false;\n for (let i = 1; i < headings.length; i++) {\n const prev = headings[i - 1].level;\n const curr = headings[i].level;\n // A skip occurs when a heading goes deeper by more than 1 level\n if (curr > prev + 1) {\n hasSkip = true;\n skipDetails.push(`${page.url}: h${prev} -> h${curr} (skipped h${prev + 1})`);\n break;\n }\n }\n if (hasSkip) pagesWithSkips++;\n }\n\n if (!hasEnoughHeadings) {\n return this.warn(\n 'Page has fewer than 2 headings — cannot evaluate heading hierarchy.',\n 'No heading level skips (e.g. h1 -> h3 without h2)',\n 'Insufficient headings to evaluate',\n {\n priority: 'medium',\n description:\n 'AI systems build content outlines from headings to understand document structure. Pages need at least two headings to form a hierarchy that can be evaluated for proper sequencing.',\n code: '<h1>Page Title</h1>\\n<h2>Section</h2>\\n<h3>Subsection</h3>',\n },\n );\n }\n\n const pass = pagesWithSkips === 0;\n const majorityPass = pagesWithSkips <= Math.floor(totalPages / 2);\n\n if (pass) {\n return this.pass(\n 'All pages have sequential heading hierarchy with no level skips.',\n 'No heading level skips (e.g. h1 -> h3 without h2)',\n 'No heading skips detected',\n );\n }\n\n if (majorityPass) {\n return this.warn(\n `${pagesWithSkips}/${totalPages} page(s) have heading level skips.`,\n 'No heading level skips (e.g. h1 -> h3 without h2)',\n skipDetails.slice(0, 3).join('; '),\n {\n priority: 'high',\n description:\n 'AI systems build content outlines from headings to understand document structure. Skipped levels (e.g., h1 to h3 without h2) break the hierarchy, causing agents to misinterpret section nesting and produce inaccurate content summaries. Fix heading levels to follow a sequential order.',\n code: '<h1>Page Title</h1>\\n<h2>Section</h2>\\n<h3>Subsection</h3>',\n },\n );\n }\n\n return this.fail(\n `${pagesWithSkips}/${totalPages} page(s) have heading level skips.`,\n 'No heading level skips (e.g. h1 -> h3 without h2)',\n skipDetails.slice(0, 3).join('; '),\n {\n priority: 'high',\n description:\n 'AI systems build content outlines from headings to understand document structure. Skipped levels (e.g., h1 to h3 without h2) break the hierarchy, causing agents to misinterpret section nesting and produce inaccurate content summaries. Fix heading levels to follow a sequential order.',\n code: '<h1>Page Title</h1>\\n<h2>Section</h2>\\n<h3>Subsection</h3>',\n },\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class MainElementAudit extends Audit {\n static override meta: AuditMeta = {\n id: '6.3',\n category: 'semantic-html',\n title: '<main> element present',\n failureTitle: '<main> element present',\n description:\n 'AI scrapers use <main> to identify primary content and discard nav/footer chrome, reducing hallucination risk from boilerplate text. Without <main>, agents must guess which content is primary versus navigational, often ingesting menus and footers into their context window.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'high',\n guidance: {\n impact:\n 'Without a <main> element, AI scrapers cannot distinguish primary content from navigation, sidebars, and footer boilerplate. This causes agents to ingest menus, disclaimers, and repeated chrome into their context window, increasing hallucination risk and reducing answer relevance.',\n fix: 'Add a single <main> element to every page wrapping only the primary content area. Do not include site navigation, sidebars, or footers inside <main>. There should be exactly one <main> per page.',\n code: '<body>\\n <header><!-- Navigation --></header>\\n <main>\\n <!-- Primary page content only -->\\n </main>\\n <footer><!-- Footer --></footer>\\n</body>',\n effort: 'easy',\n docsUrl: 'https://developer.mozilla.org/en-US/docs/Web/HTML/Element/main',\n tags: ['landmarks', 'main', 'structure', 'semantic', 'html'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n let pagesWithMain = 0;\n\n for (const page of ctx.pages) {\n if (page.$('main').length > 0) pagesWithMain++;\n }\n\n const allPass = pagesWithMain === ctx.pages.length;\n const homepagePass = ctx.pages[0] && ctx.pages[0].$('main').length > 0;\n\n if (allPass) {\n return this.pass(\n 'All pages have a <main> element.',\n '<main> element present on all pages',\n `${pagesWithMain}/${ctx.pages.length} pages with <main>`,\n );\n }\n\n if (homepagePass) {\n return this.warn(\n `${pagesWithMain}/${ctx.pages.length} page(s) have a <main> element.`,\n '<main> element present on all pages',\n `${pagesWithMain}/${ctx.pages.length} pages with <main>`,\n );\n }\n\n return this.fail(\n `${pagesWithMain}/${ctx.pages.length} page(s) have a <main> element.`,\n '<main> element present on all pages',\n `${pagesWithMain}/${ctx.pages.length} pages with <main>`,\n {\n priority: 'high',\n description:\n 'AI scrapers use <main> to identify primary content and discard nav/footer chrome, reducing hallucination risk from boilerplate text. Without <main>, agents must guess which content is primary versus navigational, often ingesting menus and footers into their context window.',\n code: '<main>\\n <!-- Primary page content here -->\\n</main>',\n },\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class ArticleElementAudit extends Audit {\n static override meta: AuditMeta = {\n id: '6.4',\n category: 'semantic-html',\n title: '<article> used for content',\n failureTitle: '<article> used for content',\n description:\n 'RAG systems chunk content by <article> boundaries for vector embedding, treating each article as an independent retrieval unit. Without <article> tags, AI chunking algorithms fall back to arbitrary text splitting, which fragments related content across multiple embeddings and reduces answer quality.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n applicablePageTypes: ['content'],\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'RAG systems chunk content by <article> boundaries for vector embedding, treating each article as an independent retrieval unit. Without <article> tags, AI chunking algorithms fall back to arbitrary text splitting, which fragments related content across embeddings and reduces answer quality.',\n fix: 'Wrap each self-contained content block (blog post, news story, product card, forum post) in an <article> element. Each <article> should make sense on its own and include a heading.',\n code: '<article>\\n <h2>Article Title</h2>\\n <p>Self-contained content block that makes sense independently...</p>\\n</article>',\n effort: 'easy',\n docsUrl: 'https://developer.mozilla.org/en-US/docs/Web/HTML/Element/article',\n tags: ['article', 'structure', 'semantic', 'html'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n let pagesWithArticle = 0;\n\n for (const page of ctx.pages) {\n if (page.$('article').length > 0) pagesWithArticle++;\n }\n\n const majorityPass =\n pagesWithArticle > Math.floor(ctx.pages.length / 2) ||\n (ctx.pages[0] && ctx.pages[0].$('article').length > 0);\n const allPass = pagesWithArticle === ctx.pages.length;\n\n if (allPass) {\n return this.pass(\n 'All content pages use <article> elements.',\n '<article> elements on content pages',\n `${pagesWithArticle}/${ctx.pages.length} pages with <article>`,\n );\n }\n\n if (majorityPass) {\n return this.warn(\n `${pagesWithArticle}/${ctx.pages.length} page(s) use <article> elements.`,\n '<article> elements on content pages',\n `${pagesWithArticle}/${ctx.pages.length} pages with <article>`,\n );\n }\n\n return this.fail(\n `${pagesWithArticle}/${ctx.pages.length} page(s) use <article> elements.`,\n '<article> elements on content pages',\n `${pagesWithArticle}/${ctx.pages.length} pages with <article>`,\n {\n priority: 'medium',\n description:\n 'RAG systems chunk content by <article> boundaries for vector embedding, treating each article as an independent retrieval unit. Without <article> tags, AI chunking algorithms fall back to arbitrary text splitting, which fragments related content across multiple embeddings and reduces answer quality.',\n code: '<article>\\n <h2>Article Title</h2>\\n <p>Self-contained content block...</p>\\n</article>',\n },\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class HeaderFooterAudit extends Audit {\n static override meta: AuditMeta = {\n id: '6.5',\n category: 'semantic-html',\n title: '<header> and <footer> landmarks',\n failureTitle: '<header> and <footer> landmarks',\n description:\n 'AI agents use <header> and <footer> landmarks to identify and exclude boilerplate content (navigation, copyright, links) from primary content extraction. Without these landmarks, agents may include footer disclaimers or nav menus in their content summaries.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'AI agents use <header> and <footer> landmarks to identify and exclude boilerplate content (navigation menus, copyright notices, legal links) from primary content extraction. Without these landmarks, agents may include footer disclaimers or nav menus in their content summaries, reducing answer accuracy.',\n fix: 'Wrap your site navigation and branding area in a <header> element, and your copyright, legal links, and secondary navigation in a <footer> element. These should be present on every page for consistent content extraction.',\n code: '<header>\\n <nav><!-- Site navigation --></nav>\\n</header>\\n<main><!-- Primary content --></main>\\n<footer>\\n <p>&copy; 2025 Your Company. All rights reserved.</p>\\n</footer>',\n effort: 'easy',\n docsUrl: 'https://developer.mozilla.org/en-US/docs/Web/HTML/Element/header',\n tags: ['landmarks', 'header', 'footer', 'structure', 'semantic', 'html'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n let pagesWithBoth = 0;\n let pagesWithHeader = 0;\n let pagesWithFooter = 0;\n\n for (const page of ctx.pages) {\n const hasHeader = page.$('header').length > 0;\n const hasFooter = page.$('footer').length > 0;\n if (hasHeader) pagesWithHeader++;\n if (hasFooter) pagesWithFooter++;\n if (hasHeader && hasFooter) pagesWithBoth++;\n }\n\n const allPass = pagesWithBoth === ctx.pages.length;\n const homepagePass =\n ctx.pages[0] && ctx.pages[0].$('header').length > 0 && ctx.pages[0].$('footer').length > 0;\n\n if (allPass) {\n return this.pass(\n 'All pages have both <header> and <footer> landmarks.',\n 'Both <header> and <footer> present on all pages',\n `${pagesWithBoth}/${ctx.pages.length} pages with both landmarks`,\n );\n }\n\n if (homepagePass) {\n return this.warn(\n `Header found on ${pagesWithHeader}/${ctx.pages.length} pages, footer on ${pagesWithFooter}/${ctx.pages.length} pages.`,\n 'Both <header> and <footer> present on all pages',\n `${pagesWithBoth}/${ctx.pages.length} pages with both landmarks`,\n );\n }\n\n return this.fail(\n `Header found on ${pagesWithHeader}/${ctx.pages.length} pages, footer on ${pagesWithFooter}/${ctx.pages.length} pages.`,\n 'Both <header> and <footer> present on all pages',\n `${pagesWithBoth}/${ctx.pages.length} pages with both landmarks`,\n {\n priority: 'medium',\n description:\n 'AI agents use <header> and <footer> landmarks to identify and exclude boilerplate content (navigation, copyright, links) from primary content extraction. Without these landmarks, agents may include footer disclaimers or nav menus in their content summaries.',\n code: '<header><!-- Site navigation --></header>\\n<main><!-- Content --></main>\\n<footer><!-- Copyright, links --></footer>',\n },\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class AsideElementAudit extends Audit {\n static override meta: AuditMeta = {\n id: '6.6',\n category: 'semantic-html',\n title: '<aside> for supplementary content',\n failureTitle: '<aside> for supplementary content',\n description:\n 'AI agents use <aside> to distinguish supplementary content (sidebars, callouts, related links) from primary content. Without it, sidebar content may be mixed into the main content extraction, diluting the primary message in AI-generated summaries.',\n scoreDisplayMode: 'binary',\n weight: 1.0,\n applicablePageTypes: ['content'],\n defaultPriority: 'low',\n guidance: {\n impact:\n 'Without <aside>, AI agents cannot distinguish supplementary content (sidebars, callouts, related links) from primary content. This causes sidebar promotions, ads, and tangential content to be mixed into AI-generated summaries, diluting the accuracy of your main message.',\n fix: 'Wrap sidebar content, callout boxes, pull quotes, and related-links sections in <aside> elements. This signals to AI agents that the content is supplementary and should not be treated as part of the main narrative.',\n code: '<aside>\\n <h3>Related Resources</h3>\\n <ul>\\n <li><a href=\"/related-topic\">Related Topic</a></li>\\n </ul>\\n</aside>',\n effort: 'easy',\n docsUrl: 'https://developer.mozilla.org/en-US/docs/Web/HTML/Element/aside',\n tags: ['aside', 'structure', 'semantic', 'html'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n let pagesWithAside = 0;\n\n for (const page of ctx.pages) {\n if (page.$('aside').length > 0) pagesWithAside++;\n }\n\n const hasAside = pagesWithAside > 0;\n\n if (hasAside) {\n return this.pass(\n `${pagesWithAside}/${ctx.pages.length} page(s) use <aside> for supplementary content.`,\n '<aside> used for supplementary/sidebar content where applicable',\n `${pagesWithAside} page(s) with <aside>`,\n );\n }\n\n return this.warn(\n 'No <aside> elements found. If sidebar or supplementary content exists, consider using <aside>.',\n '<aside> used for supplementary/sidebar content where applicable',\n 'No <aside> elements found',\n {\n priority: 'low',\n description:\n 'AI agents use <aside> to distinguish supplementary content (sidebars, callouts, related links) from primary content. Without it, sidebar content may be mixed into the main content extraction, diluting the primary message in AI-generated summaries.',\n code: '<aside>\\n <h3>Related Resources</h3>\\n <ul><li><a href=\"/related\">Related page</a></li></ul>\\n</aside>',\n },\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class SectionHeadingsAudit extends Audit {\n static override meta: AuditMeta = {\n id: '6.7',\n category: 'semantic-html',\n title: '<section> elements have headings or labels',\n failureTitle: '<section> elements have headings or labels',\n description:\n 'AI agents use section headings to build a topic map of your page for retrieval-augmented generation (RAG). Unlabeled sections are opaque to AI systems that chunk content by semantic boundaries, reducing the quality of retrieved context for answer generation.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'AI agents use section headings to build a topic map of your page for retrieval-augmented generation. Unlabeled <section> elements are opaque to AI chunking systems, preventing them from indexing and retrieving your content by topic, which reduces your visibility in AI-generated answers.',\n fix: 'Add a heading (h2-h6) as the first child of every <section> element, or use aria-label/aria-labelledby if a visible heading is not appropriate for the design. Every section should have a clear, descriptive label.',\n code: '<section>\\n <h2>Pricing Plans</h2>\\n <p>Choose the plan that fits your needs...</p>\\n</section>\\n\\n<!-- Or with aria-label for visually hidden labels: -->\\n<section aria-label=\"Customer testimonials\">\\n <!-- Content without a visible heading -->\\n</section>',\n effort: 'easy',\n docsUrl: 'https://developer.mozilla.org/en-US/docs/Web/HTML/Element/section',\n tags: ['sections', 'headings', 'structure', 'semantic', 'html'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n let totalSections = 0;\n let labeledSections = 0;\n\n for (const page of ctx.pages) {\n const $ = page.$;\n $('section').each((_, el) => {\n totalSections++;\n const hasHeading =\n $(el).find('> h1, > h2, > h3, > h4, > h5, > h6').length > 0 ||\n $(el).find('h1, h2, h3, h4, h5, h6').length > 0;\n const hasAriaLabel = !!$(el).attr('aria-label');\n const hasAriaLabelledby = !!$(el).attr('aria-labelledby');\n\n if (hasHeading || hasAriaLabel || hasAriaLabelledby) {\n labeledSections++;\n }\n });\n }\n\n if (totalSections === 0) {\n return this.warn(\n 'No <section> elements found on any page.',\n 'All <section> elements have a heading or aria-label',\n 'No <section> elements',\n {\n priority: 'medium',\n description:\n 'AI agents use <section> elements with headings to identify thematic content groups for chunked retrieval. Consider using <section> elements to group related content, each with a descriptive heading that AI systems can use for topic classification.',\n code: '<section>\\n <h2>Section Topic</h2>\\n <p>Content about this topic...</p>\\n</section>',\n },\n );\n }\n\n const allLabeled = labeledSections === totalSections;\n const majorityLabeled = labeledSections > totalSections / 2;\n\n if (allLabeled) {\n return this.pass(\n `All ${totalSections} <section> element(s) have a heading or label.`,\n 'All <section> elements have a heading child or aria-label/aria-labelledby',\n `${labeledSections}/${totalSections} labeled sections`,\n );\n }\n\n if (majorityLabeled) {\n return this.warn(\n `${labeledSections}/${totalSections} <section> element(s) have a heading or label.`,\n 'All <section> elements have a heading child or aria-label/aria-labelledby',\n `${labeledSections}/${totalSections} labeled sections`,\n {\n priority: 'medium',\n description:\n 'AI agents use section headings to build a topic map of your page for retrieval-augmented generation (RAG). Unlabeled sections are opaque to AI systems that chunk content by semantic boundaries, reducing the quality of retrieved context for answer generation.',\n code: '<section aria-label=\"Pricing details\">\\n <h2>Pricing</h2>\\n <p>Content...</p>\\n</section>',\n },\n );\n }\n\n return this.fail(\n `${labeledSections}/${totalSections} <section> element(s) have a heading or label.`,\n 'All <section> elements have a heading child or aria-label/aria-labelledby',\n `${labeledSections}/${totalSections} labeled sections`,\n {\n priority: 'medium',\n description:\n 'AI agents use section headings to build a topic map of your page for retrieval-augmented generation (RAG). Unlabeled sections are opaque to AI systems that chunk content by semantic boundaries, reducing the quality of retrieved context for answer generation.',\n code: '<section aria-label=\"Pricing details\">\\n <h2>Pricing</h2>\\n <p>Content...</p>\\n</section>',\n },\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class SemanticListsAudit extends Audit {\n static override meta: AuditMeta = {\n id: '6.8',\n category: 'semantic-html',\n title: 'Semantic list usage',\n failureTitle: 'Semantic list usage',\n description:\n 'AI agents recognize <ul>, <ol>, and <dl> as structured data lists and extract them as bullet points in generated answers. Content formatted as styled divs instead of semantic lists is invisible to list-extraction algorithms, meaning your feature lists and step-by-step content will not be surfaced as structured answers.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'AI agents recognize <ul>, <ol>, and <dl> as structured lists and extract them as bullet points or numbered steps in generated answers. Content formatted as styled <div> elements instead of semantic lists is invisible to list-extraction algorithms, so your feature lists and step-by-step instructions will not be surfaced as structured answers.',\n fix: 'Replace styled <div> elements used as lists with proper <ul> (unordered), <ol> (ordered), or <dl> (definition) elements. Use <ol> for sequential steps, <ul> for unordered items, and <dl> for term-definition pairs.',\n code: '<ul>\\n <li>Feature one: description</li>\\n <li>Feature two: description</li>\\n</ul>\\n\\n<ol>\\n <li>Step one</li>\\n <li>Step two</li>\\n</ol>',\n effort: 'easy',\n docsUrl: 'https://developer.mozilla.org/en-US/docs/Web/HTML/Element/ul',\n tags: ['lists', 'structure', 'semantic', 'html'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n let pagesWithSemanticLists = 0;\n\n for (const page of ctx.pages) {\n const $ = page.$;\n const hasLists = $('ul').length > 0 || $('ol').length > 0 || $('dl').length > 0;\n if (hasLists) pagesWithSemanticLists++;\n }\n\n const allPass = pagesWithSemanticLists === ctx.pages.length;\n const majorityPass = pagesWithSemanticLists > ctx.pages.length / 2;\n\n if (allPass) {\n return this.pass(\n 'All pages use semantic list elements (<ul>, <ol>, <dl>).',\n 'Lists use <ul>, <ol>, or <dl> instead of styled divs',\n `${pagesWithSemanticLists}/${ctx.pages.length} pages with semantic lists`,\n );\n }\n\n if (majorityPass) {\n return this.warn(\n `${pagesWithSemanticLists}/${ctx.pages.length} page(s) use semantic list elements.`,\n 'Lists use <ul>, <ol>, or <dl> instead of styled divs',\n `${pagesWithSemanticLists}/${ctx.pages.length} pages with semantic lists`,\n {\n priority: 'medium',\n description:\n 'AI agents recognize <ul>, <ol>, and <dl> as structured data lists and extract them as bullet points in generated answers. Content formatted as styled divs instead of semantic lists is invisible to list-extraction algorithms, meaning your feature lists and step-by-step content will not be surfaced as structured answers.',\n code: '<ul>\\n <li>Feature one</li>\\n <li>Feature two</li>\\n</ul>',\n },\n );\n }\n\n return this.fail(\n `${pagesWithSemanticLists}/${ctx.pages.length} page(s) use semantic list elements.`,\n 'Lists use <ul>, <ol>, or <dl> instead of styled divs',\n `${pagesWithSemanticLists}/${ctx.pages.length} pages with semantic lists`,\n {\n priority: 'medium',\n description:\n 'AI agents recognize <ul>, <ol>, and <dl> as structured data lists and extract them as bullet points in generated answers. Content formatted as styled divs instead of semantic lists is invisible to list-extraction algorithms, meaning your feature lists and step-by-step content will not be surfaced as structured answers.',\n code: '<ul>\\n <li>Feature one</li>\\n <li>Feature two</li>\\n</ul>',\n },\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class DataTablesAudit extends Audit {\n static override meta: AuditMeta = {\n id: '6.9',\n category: 'semantic-html',\n title: 'Data tables properly structured',\n failureTitle: 'Data tables properly structured',\n description:\n 'AI agents use <thead> and <th> elements to understand column headers and interpret table data correctly. Without proper structure, agents cannot map cell values to their column meanings, leading to garbled data extraction in AI-generated comparisons and summaries.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'AI agents rely on <thead> and <th> elements to understand column headers and map cell values to their meanings. Without proper table structure, agents cannot interpret tabular data correctly, leading to garbled comparisons and inaccurate data extraction in AI-generated summaries.',\n fix: 'Add a <thead> section containing a <tr> with <th> elements for each column header. Place data rows inside a <tbody> section. Use the scope attribute on <th> elements for complex tables with row and column headers.',\n code: '<table>\\n <thead>\\n <tr><th scope=\"col\">Feature</th><th scope=\"col\">Value</th></tr>\\n </thead>\\n <tbody>\\n <tr><td>Speed</td><td>100ms</td></tr>\\n </tbody>\\n</table>',\n effort: 'easy',\n docsUrl: 'https://developer.mozilla.org/en-US/docs/Web/HTML/Element/table',\n tags: ['tables', 'structure', 'semantic', 'html'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n let totalTables = 0;\n let properTables = 0;\n\n for (const page of ctx.pages) {\n const $ = page.$;\n $('table').each((_, el) => {\n totalTables++;\n const hasTh = $(el).find('th').length > 0;\n const hasThead = $(el).find('thead').length > 0;\n // Accept tables with th in thead (column headers) or tbody (row headers)\n if (hasTh && (hasThead || $(el).find('tbody th').length > 0)) properTables++;\n });\n }\n\n if (totalTables === 0) {\n return this.pass(\n 'No data tables found — check not applicable.',\n 'Tables have <thead> and <th> elements',\n 'No <table> elements',\n );\n }\n\n const allProper = properTables === totalTables;\n const majorityProper = properTables > totalTables / 2;\n\n if (allProper) {\n return this.pass(\n `All ${totalTables} table(s) have proper <thead> and <th> structure.`,\n 'All <table> elements have <thead> and <th>',\n `${properTables}/${totalTables} properly structured tables`,\n );\n }\n\n if (majorityProper) {\n return this.warn(\n `${properTables}/${totalTables} table(s) have proper <thead> and <th> structure.`,\n 'All <table> elements have <thead> and <th>',\n `${properTables}/${totalTables} properly structured tables`,\n {\n priority: 'medium',\n description:\n 'AI agents use <thead> and <th> elements to understand column headers and interpret table data correctly. Without proper structure, agents cannot map cell values to their column meanings, leading to garbled data extraction in AI-generated comparisons and summaries.',\n code: '<table>\\n <thead><tr><th>Feature</th><th>Value</th></tr></thead>\\n <tbody><tr><td>Speed</td><td>100ms</td></tr></tbody>\\n</table>',\n },\n );\n }\n\n return this.fail(\n `${properTables}/${totalTables} table(s) have proper <thead> and <th> structure.`,\n 'All <table> elements have <thead> and <th>',\n `${properTables}/${totalTables} properly structured tables`,\n {\n priority: 'medium',\n description:\n 'AI agents use <thead> and <th> elements to understand column headers and interpret table data correctly. Without proper structure, agents cannot map cell values to their column meanings, leading to garbled data extraction in AI-generated comparisons and summaries.',\n code: '<table>\\n <thead><tr><th>Feature</th><th>Value</th></tr></thead>\\n <tbody><tr><td>Speed</td><td>100ms</td></tr></tbody>\\n</table>',\n },\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class CodeLanguageAudit extends Audit {\n static override meta: AuditMeta = {\n id: '6.10',\n category: 'semantic-html',\n title: 'Code blocks have language annotations',\n failureTitle: 'Code blocks have language annotations',\n description:\n 'AI agents use language annotations on code blocks to apply the correct syntax understanding and provide accurate code explanations. Without them, agents must guess the programming language, which can lead to incorrect interpretations in AI-generated code answers.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n applicablePageTypes: ['content'],\n defaultPriority: 'low',\n guidance: {\n impact:\n 'AI agents use language annotations on code blocks to apply correct syntax highlighting and interpretation. Without language classes, agents must guess the programming language, leading to incorrect code explanations and potentially dangerous misinterpretations in AI-generated technical answers.',\n fix: 'Add a class attribute with a \"language-\" prefix to every <code> element inside <pre>. Use the standard language identifier (e.g., language-javascript, language-python, language-html). Most syntax highlighting libraries (Prism, Highlight.js) do this automatically.',\n code: '<pre><code class=\"language-javascript\">\\nconst response = await fetch(\"/api/data\");\\nconst data = await response.json();\\n</code></pre>',\n effort: 'trivial',\n docsUrl: 'https://developer.mozilla.org/en-US/docs/Web/HTML/Element/code',\n tags: ['code', 'language', 'semantic', 'html'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n let totalCodeBlocks = 0;\n let annotatedBlocks = 0;\n\n for (const page of ctx.pages) {\n const $ = page.$;\n $('pre code').each((_, el) => {\n totalCodeBlocks++;\n const classList = $(el).attr('class') ?? '';\n if (classList.includes('language-')) annotatedBlocks++;\n });\n }\n\n if (totalCodeBlocks === 0) {\n return this.warn(\n 'No code blocks found — check may not apply to this site.',\n '<pre><code> elements have class containing \"language-\"',\n 'No <pre><code> elements',\n {\n priority: 'low',\n description:\n 'AI agents use language annotations on code blocks to apply the correct syntax understanding and provide accurate code explanations. Without them, agents must guess the programming language, which can lead to incorrect interpretations in AI-generated code answers.',\n code: '<pre><code class=\"language-javascript\">\\nconst result = await fetch(\"/api/data\");\\n</code></pre>',\n },\n );\n }\n\n const allAnnotated = annotatedBlocks === totalCodeBlocks;\n const majorityAnnotated = annotatedBlocks > totalCodeBlocks / 2;\n\n if (allAnnotated) {\n return this.pass(\n `All ${totalCodeBlocks} code block(s) have language annotations.`,\n 'All <pre><code> elements have class containing \"language-\"',\n `${annotatedBlocks}/${totalCodeBlocks} annotated code blocks`,\n );\n }\n\n if (majorityAnnotated) {\n return this.warn(\n `${annotatedBlocks}/${totalCodeBlocks} code block(s) have language annotations.`,\n 'All <pre><code> elements have class containing \"language-\"',\n `${annotatedBlocks}/${totalCodeBlocks} annotated code blocks`,\n {\n priority: 'low',\n description:\n 'AI agents use language annotations to apply correct syntax understanding when extracting and explaining code from your pages. Unannotated code blocks force agents to guess the language, which often produces incorrect interpretations.',\n code: '<pre><code class=\"language-python\">\\nresult = requests.get(\"/api/data\")\\n</code></pre>',\n },\n );\n }\n\n return this.fail(\n `${annotatedBlocks}/${totalCodeBlocks} code block(s) have language annotations.`,\n 'All <pre><code> elements have class containing \"language-\"',\n `${annotatedBlocks}/${totalCodeBlocks} annotated code blocks`,\n {\n priority: 'low',\n description:\n 'AI agents use language annotations to apply correct syntax understanding when extracting and explaining code from your pages. Unannotated code blocks force agents to guess the language, which often produces incorrect interpretations.',\n code: '<pre><code class=\"language-python\">\\nresult = requests.get(\"/api/data\")\\n</code></pre>',\n },\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class TimeElementAudit extends Audit {\n static override meta: AuditMeta = {\n id: '6.11',\n category: 'semantic-html',\n title: '<time datetime=\"\"> used for dates',\n failureTitle: '<time datetime=\"\"> used for dates',\n description:\n 'AI agents use <time datetime> elements to reliably parse dates for freshness scoring and temporal reasoning. Without machine-readable dates, agents must regex-parse human-readable date formats, which frequently fails across locales and ambiguous formats like \"01/02/2025\".',\n scoreDisplayMode: 'binary',\n weight: 1.0,\n applicablePageTypes: ['content'],\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'AI agents use <time datetime> elements to reliably parse dates for freshness scoring and temporal reasoning. Without machine-readable dates, agents must regex-parse human-readable formats, which frequently fails across locales and ambiguous formats like \"01/02/2025\" (Jan 2 vs. Feb 1).',\n fix: 'Wrap all dates and times in <time> elements with a datetime attribute in ISO 8601 format (YYYY-MM-DD or YYYY-MM-DDThh:mm:ss). Include publication dates, event dates, and last-modified dates.',\n code: '<p>Published on <time datetime=\"2025-01-15\">January 15, 2025</time></p>\\n<p>Event starts <time datetime=\"2025-03-20T09:00:00-05:00\">March 20 at 9 AM EST</time></p>',\n effort: 'trivial',\n docsUrl: 'https://developer.mozilla.org/en-US/docs/Web/HTML/Element/time',\n tags: ['dates', 'time', 'semantic', 'html'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n let pagesWithTime = 0;\n\n for (const page of ctx.pages) {\n if (page.$('time[datetime]').length > 0) pagesWithTime++;\n }\n\n const hasTime = pagesWithTime > 0;\n\n if (hasTime) {\n return this.pass(\n `${pagesWithTime}/${ctx.pages.length} page(s) use <time datetime=\"\"> for dates.`,\n '<time datetime=\"\"> elements used for dates',\n `${pagesWithTime} page(s) with <time datetime=\"\">`,\n );\n }\n\n return this.fail(\n 'No <time datetime=\"\"> elements found on any page.',\n '<time datetime=\"\"> elements used for dates',\n 'No <time datetime=\"\"> elements',\n {\n priority: 'medium',\n description:\n 'AI agents use <time datetime> elements to reliably parse dates for freshness scoring and temporal reasoning. Without machine-readable dates, agents must regex-parse human-readable date formats, which frequently fails across locales and ambiguous formats like \"01/02/2025\".',\n code: '<time datetime=\"2025-01-15\">January 15, 2025</time>',\n },\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class AddressElementAudit extends Audit {\n static override meta: AuditMeta = {\n id: '6.12',\n category: 'semantic-html',\n title: '<address> for contact info',\n failureTitle: '<address> for contact info',\n description:\n 'AI agents use <address> elements to extract contact information (email, phone, physical address) for structured answers to \"how to contact\" queries. Without semantic <address> markup, agents must guess which text on your page is contact info.',\n scoreDisplayMode: 'binary',\n weight: 1.0,\n applicablePageTypes: ['homepage'],\n defaultPriority: 'low',\n guidance: {\n impact:\n 'AI agents cannot reliably extract contact information (email, phone, physical address) when it is not wrapped in an <address> element. This means your business contact details may be omitted from AI-generated answers to \"how do I contact\" queries.',\n fix: 'Wrap all contact information blocks (email addresses, phone numbers, physical addresses) in an <address> element. Place it in the <footer> or near the relevant content section.',\n code: '<address>\\n <a href=\"mailto:info@yoursite.com\">info@yoursite.com</a><br>\\n <a href=\"tel:+1234567890\">+1 (234) 567-890</a><br>\\n 123 Main St, City, ST 12345\\n</address>',\n effort: 'trivial',\n docsUrl: 'https://developer.mozilla.org/en-US/docs/Web/HTML/Element/address',\n tags: ['contact', 'semantic', 'html'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n let pagesWithAddress = 0;\n\n for (const page of ctx.pages) {\n if (page.$('address').length > 0) pagesWithAddress++;\n }\n\n const hasAddress = pagesWithAddress > 0;\n\n if (hasAddress) {\n return this.pass(\n `${pagesWithAddress}/${ctx.pages.length} page(s) use <address> for contact information.`,\n '<address> element used for contact information',\n `${pagesWithAddress} page(s) with <address>`,\n );\n }\n\n return this.warn(\n 'No <address> elements found. If contact information exists, consider using <address>.',\n '<address> element used for contact information',\n 'No <address> elements found',\n {\n priority: 'low',\n description:\n 'AI agents use <address> elements to extract contact information (email, phone, physical address) for structured answers to \"how to contact\" queries. Without semantic <address> markup, agents must guess which text on your page is contact info.',\n code: '<address>\\n <a href=\"mailto:info@yoursite.com\">info@yoursite.com</a><br>\\n 123 Main St, City, ST 12345\\n</address>',\n },\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class DefinitionElementsAudit extends Audit {\n static override meta: AuditMeta = {\n id: '6.13',\n category: 'semantic-html',\n title: 'Definition elements',\n failureTitle: 'Definition elements',\n description:\n 'AI agents use <dfn> and <dl> elements to extract term-definition pairs for \"what is X?\" queries. Semantic definition markup makes your glossary terms and key concepts directly extractable as AI-generated answer snippets.',\n scoreDisplayMode: 'binary',\n weight: 1.0,\n applicablePageTypes: ['content'],\n defaultPriority: 'low',\n guidance: {\n impact:\n 'AI agents use <dfn> and <dl> elements to extract term-definition pairs for \"what is X?\" queries. Without semantic definition markup, your glossary terms and key concepts cannot be directly surfaced as AI-generated answer snippets.',\n fix: 'Use <dl> (definition list) with <dt> (term) and <dd> (definition) pairs for glossaries, FAQs, and key-value content. Use <dfn> inline to mark the defining instance of a term within running text.',\n code: '<dl>\\n <dt><dfn>API Rate Limit</dfn></dt>\\n <dd>The maximum number of requests allowed per time period.</dd>\\n</dl>',\n effort: 'easy',\n docsUrl: 'https://developer.mozilla.org/en-US/docs/Web/HTML/Element/dl',\n tags: ['definitions', 'glossary', 'semantic', 'html'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n let pagesWithDefinitions = 0;\n\n for (const page of ctx.pages) {\n const $ = page.$;\n if ($('dfn').length > 0 || $('dl').length > 0) pagesWithDefinitions++;\n }\n\n const hasDefinitions = pagesWithDefinitions > 0;\n\n if (hasDefinitions) {\n return this.pass(\n `${pagesWithDefinitions}/${ctx.pages.length} page(s) use definition elements (<dfn> or <dl>).`,\n '<dfn> or <dl> elements used for definitions',\n `${pagesWithDefinitions} page(s) with definition elements`,\n );\n }\n\n return this.warn(\n 'No <dfn> or <dl> elements found. Consider using them for glossary terms or key-value content.',\n '<dfn> or <dl> elements used for definitions',\n 'No definition elements found',\n {\n priority: 'low',\n description:\n 'AI agents use <dfn> and <dl> elements to extract term-definition pairs for \"what is X?\" queries. Semantic definition markup makes your glossary terms and key concepts directly extractable as AI-generated answer snippets.',\n code: '<dl>\\n <dt><dfn>Term</dfn></dt>\\n <dd>Definition of the term in clear language.</dd>\\n</dl>',\n },\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\nimport { getWordCount } from '../../parser';\n\nexport class ContentDepthAudit extends Audit {\n static override meta: AuditMeta = {\n id: '6.14',\n category: 'semantic-html',\n title: 'Sufficient content depth',\n failureTitle: 'Sufficient content depth',\n description:\n 'AI RAG systems need sufficient content depth to generate accurate, detailed answers. Pages with fewer than 300 words provide too little context for meaningful vector embeddings, causing your content to rank poorly in retrieval and be excluded from AI-generated responses.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'Pages with fewer than 300 words provide too little context for AI RAG systems to generate accurate, detailed answers. Thin content produces weak vector embeddings that rank poorly in retrieval, causing your pages to be excluded from AI-generated responses entirely.',\n fix: 'Expand thin pages with substantive content: add detailed explanations, practical examples, FAQs, and relevant context. Aim for at least 300 words of meaningful content per page. Avoid filler text -- focus on answering real user questions comprehensively.',\n effort: 'moderate',\n tags: ['content', 'depth', 'quality'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n let pagesAboveThreshold = 0;\n const wordCounts: Array<{ url: string; count: number }> = [];\n\n for (const page of ctx.pages) {\n const count = getWordCount(page.$);\n wordCounts.push({ url: page.url, count });\n if (count > 300) pagesAboveThreshold++;\n }\n\n const allPass = pagesAboveThreshold === ctx.pages.length;\n const majorityPass = pagesAboveThreshold > ctx.pages.length / 2;\n const homepagePass = wordCounts.length > 0 && wordCounts[0].count > 300;\n\n const lowestPage = wordCounts.reduce(\n (min, wc) => (wc.count < min.count ? wc : min),\n wordCounts[0] ?? { url: '', count: 0 },\n );\n\n if (allPass) {\n return this.pass(\n 'All pages have sufficient content depth (>300 words).',\n 'More than 300 words of content per page',\n `${pagesAboveThreshold}/${ctx.pages.length} pages above threshold`,\n );\n }\n\n if (majorityPass || homepagePass) {\n return this.warn(\n `${pagesAboveThreshold}/${ctx.pages.length} page(s) have >300 words. Lowest: ${lowestPage.count} words.`,\n 'More than 300 words of content per page',\n `${pagesAboveThreshold}/${ctx.pages.length} pages above threshold`,\n {\n priority: 'medium',\n description:\n 'AI RAG systems need sufficient content depth to generate accurate, detailed answers. Pages with fewer than 300 words provide too little context for meaningful vector embeddings, causing your content to rank poorly in retrieval and be excluded from AI-generated responses.',\n code: '<!-- Ensure each page has 300+ words of substantive content -->\\n<!-- Expand thin pages with detailed explanations, examples, and context -->',\n },\n );\n }\n\n return this.fail(\n `${pagesAboveThreshold}/${ctx.pages.length} page(s) have >300 words. Lowest: ${lowestPage.count} words.`,\n 'More than 300 words of content per page',\n `${pagesAboveThreshold}/${ctx.pages.length} pages above threshold`,\n {\n priority: 'medium',\n description:\n 'AI RAG systems need sufficient content depth to generate accurate, detailed answers. Pages with fewer than 300 words provide too little context for meaningful vector embeddings, causing your content to rank poorly in retrieval and be excluded from AI-generated responses.',\n code: '<!-- Ensure each page has 300+ words of substantive content -->\\n<!-- Expand thin pages with detailed explanations, examples, and context -->',\n },\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\nimport { extractImages } from '../../parser';\n\nexport class ImageAltTextAudit extends Audit {\n static override meta: AuditMeta = {\n id: '6.15',\n category: 'semantic-html',\n title: 'Image alt text coverage',\n failureTitle: 'Image alt text coverage',\n description:\n 'Most AI agents are text-only and rely entirely on alt text to understand images. Missing alt text makes your visual content invisible to AI systems, meaning product images, diagrams, and infographics contribute nothing to AI-generated answers about your page.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'high',\n guidance: {\n impact:\n 'Most AI agents are text-only and rely entirely on alt text to understand images. Missing alt text makes your product photos, diagrams, and infographics completely invisible to AI systems, meaning they contribute nothing to AI-generated answers about your pages.',\n fix: 'Add descriptive alt text to every non-decorative image. Describe what the image shows and why it matters in context. For product images, include the product name and key visual features. For decorative images, use an empty alt=\"\" with role=\"presentation\" instead.',\n code: '<img src=\"product.jpg\" alt=\"Blue running shoe, side view, with breathable mesh upper and cushioned sole\">',\n effort: 'moderate',\n docsUrl: 'https://developer.mozilla.org/en-US/docs/Web/API/HTMLImageElement/alt',\n tags: ['images', 'alt-text', 'accessibility', 'semantic'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n let totalImages = 0;\n let imagesWithAlt = 0;\n\n for (const page of ctx.pages) {\n const images = extractImages(page.$);\n for (const img of images) {\n // Skip images explicitly marked decorative — they intentionally have no\n // informative alt text and are covered by the decorative-images audit (6.16):\n // - an empty `alt=\"\"` (present but blank) signals decorative intent, OR\n // - role=\"presentation\"/\"none\" removes the image from the accessibility tree.\n // An img with NO alt attribute at all (hasAlt === false) is a real failure\n // and is still counted against coverage below.\n const isExplicitlyEmptyAlt = img.hasAlt && img.alt === '';\n const isPresentationRole = img.role === 'presentation' || img.role === 'none';\n if (isExplicitlyEmptyAlt || isPresentationRole) continue;\n\n totalImages++;\n if (img.alt && img.alt.trim().length > 0) {\n imagesWithAlt++;\n }\n }\n }\n\n if (totalImages === 0) {\n return this.pass(\n 'No non-decorative images found — check not applicable.',\n '100% of non-decorative images have descriptive alt text',\n 'No non-decorative images',\n );\n }\n\n const coverage = imagesWithAlt / totalImages;\n const allCovered = coverage === 1;\n const mostCovered = coverage >= 0.8;\n\n if (allCovered) {\n return this.pass(\n `All ${totalImages} non-decorative image(s) have descriptive alt text.`,\n '100% of non-decorative images have non-empty descriptive alt text',\n `${imagesWithAlt}/${totalImages} images with alt text (${Math.round(coverage * 100)}%)`,\n );\n }\n\n if (mostCovered) {\n return this.warn(\n `${imagesWithAlt}/${totalImages} non-decorative image(s) have alt text (${Math.round(coverage * 100)}%).`,\n '100% of non-decorative images have non-empty descriptive alt text',\n `${imagesWithAlt}/${totalImages} images with alt text (${Math.round(coverage * 100)}%)`,\n {\n priority: 'high',\n description:\n 'Most AI agents are text-only and rely entirely on alt text to understand images. Missing alt text makes your visual content invisible to AI systems, meaning product images, diagrams, and infographics contribute nothing to AI-generated answers about your page.',\n code: '<img src=\"product.jpg\" alt=\"Product name shown from the front, featuring key design element\">',\n },\n );\n }\n\n return this.fail(\n `${imagesWithAlt}/${totalImages} non-decorative image(s) have alt text (${Math.round(coverage * 100)}%).`,\n '100% of non-decorative images have non-empty descriptive alt text',\n `${imagesWithAlt}/${totalImages} images with alt text (${Math.round(coverage * 100)}%)`,\n {\n priority: 'high',\n description:\n 'Most AI agents are text-only and rely entirely on alt text to understand images. Missing alt text makes your visual content invisible to AI systems, meaning product images, diagrams, and infographics contribute nothing to AI-generated answers about your page.',\n code: '<img src=\"product.jpg\" alt=\"Product name shown from the front, featuring key design element\">',\n },\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\nimport { extractImages } from '../../parser';\n\nexport class DecorativeImagesAudit extends Audit {\n static override meta: AuditMeta = {\n id: '6.16',\n category: 'semantic-html',\n title: 'Decorative images marked correctly',\n failureTitle: 'Decorative images marked correctly',\n description:\n 'AI agents processing the accessibility tree treat images with empty alt but no role=\"presentation\" as potentially missing alt text rather than intentionally decorative. Adding role=\"presentation\" explicitly tells agents to skip these images, preventing them from flagging false content gaps.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'AI agents processing the accessibility tree treat images with empty alt but no role=\"presentation\" as potentially missing alt text rather than intentionally decorative. This creates false-positive content gaps and wastes agent processing on irrelevant images.',\n fix: 'Add role=\"presentation\" (or role=\"none\") to all decorative images that already have an empty alt attribute. This explicitly tells AI agents and assistive technologies to skip these images entirely.',\n code: '<img src=\"decorative-border.png\" alt=\"\" role=\"presentation\">',\n effort: 'trivial',\n docsUrl:\n 'https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/presentation_role',\n tags: ['images', 'decorative', 'accessibility', 'semantic'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n let decorativeCount = 0;\n let correctlyMarked = 0;\n\n for (const page of ctx.pages) {\n const images = extractImages(page.$);\n for (const img of images) {\n // An image with empty alt is considered decorative\n if (img.alt === '') {\n decorativeCount++;\n if (img.role === 'presentation') {\n correctlyMarked++;\n }\n }\n }\n }\n\n if (decorativeCount === 0) {\n return this.pass(\n 'No decorative images (empty alt) found — check not applicable.',\n 'Images with empty alt have role=\"presentation\"',\n 'No images with empty alt',\n );\n }\n\n const allCorrect = correctlyMarked === decorativeCount;\n const majorityCorrect = correctlyMarked > decorativeCount / 2;\n\n if (allCorrect) {\n return this.pass(\n `All ${decorativeCount} decorative image(s) have role=\"presentation\".`,\n 'Images with empty alt have role=\"presentation\"',\n `${correctlyMarked}/${decorativeCount} correctly marked`,\n );\n }\n\n if (majorityCorrect) {\n return this.warn(\n `${correctlyMarked}/${decorativeCount} decorative image(s) have role=\"presentation\".`,\n 'Images with empty alt have role=\"presentation\"',\n `${correctlyMarked}/${decorativeCount} correctly marked`,\n {\n priority: 'medium',\n description:\n 'AI agents processing the accessibility tree treat images with empty alt but no role=\"presentation\" as potentially missing alt text rather than intentionally decorative. Adding role=\"presentation\" explicitly tells agents to skip these images, preventing them from flagging false content gaps.',\n code: '<img src=\"decorative-bg.png\" alt=\"\" role=\"presentation\">',\n },\n );\n }\n\n return this.fail(\n `${correctlyMarked}/${decorativeCount} decorative image(s) have role=\"presentation\".`,\n 'Images with empty alt have role=\"presentation\"',\n `${correctlyMarked}/${decorativeCount} correctly marked`,\n {\n priority: 'medium',\n description:\n 'AI agents processing the accessibility tree treat images with empty alt but no role=\"presentation\" as potentially missing alt text rather than intentionally decorative. Adding role=\"presentation\" explicitly tells agents to skip these images, preventing them from flagging false content gaps.',\n code: '<img src=\"decorative-bg.png\" alt=\"\" role=\"presentation\">',\n },\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\nimport { extractImages } from '../../parser';\n\nexport class FigureFigcaptionAudit extends Audit {\n static override meta: AuditMeta = {\n id: '6.17',\n category: 'semantic-html',\n title: '<figure> + <figcaption> usage',\n failureTitle: '<figure> + <figcaption> usage',\n description:\n 'AI agents use <figcaption> to understand the purpose and context of figures beyond what alt text provides. Without captions, agents treat figures as opaque image containers with no semantic meaning, missing opportunities to cite your visual data in AI-generated answers.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'AI agents use <figcaption> to understand the purpose and context of visual content beyond what alt text provides. Without captions, figures are treated as opaque image containers, and your charts, diagrams, and illustrations cannot be meaningfully cited in AI-generated answers.',\n fix: 'Wrap images, charts, diagrams, and code examples in <figure> elements. Add a descriptive <figcaption> that explains the significance of the visual content -- not just what it shows, but why it matters in context.',\n code: '<figure>\\n <img src=\"sales-chart.png\" alt=\"Bar chart showing quarterly sales\">\\n <figcaption>Figure 1: Sales increased 40% year-over-year in Q4 2024, driven by the new product launch.</figcaption>\\n</figure>',\n effort: 'easy',\n docsUrl: 'https://developer.mozilla.org/en-US/docs/Web/HTML/Element/figure',\n tags: ['images', 'figures', 'captions', 'semantic', 'html'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n let totalFigures = 0;\n let figuresWithCaption = 0;\n\n for (const page of ctx.pages) {\n const $ = page.$;\n $('figure').each((_, el) => {\n totalFigures++;\n if ($(el).find('figcaption').length > 0) {\n figuresWithCaption++;\n }\n });\n }\n\n if (totalFigures === 0) {\n // Check if there are images that could benefit from figure/figcaption\n let totalImages = 0;\n for (const page of ctx.pages) {\n totalImages += extractImages(page.$).length;\n }\n\n if (totalImages > 0) {\n return this.warn(\n `No <figure> elements found, but ${totalImages} image(s) exist that could benefit from <figure>/<figcaption>.`,\n 'Images with context wrapped in <figure> with <figcaption>',\n 'No <figure> elements',\n {\n priority: 'low',\n description:\n 'AI agents use <figcaption> to understand the context and purpose of images beyond what alt text provides. Wrapping images in <figure> with <figcaption> gives agents a richer description that can be cited in AI-generated explanations.',\n code: '<figure>\\n <img src=\"chart.png\" alt=\"Sales growth chart\">\\n <figcaption>Figure 1: Sales grew 40% year-over-year in Q4 2024.</figcaption>\\n</figure>',\n },\n );\n }\n\n return this.pass(\n 'No images or <figure> elements found — check not applicable.',\n 'Images with context wrapped in <figure> with <figcaption>',\n 'No <figure> elements',\n );\n }\n\n const allHaveCaptions = figuresWithCaption === totalFigures;\n const majorityHaveCaptions = figuresWithCaption > totalFigures / 2;\n\n if (allHaveCaptions) {\n return this.pass(\n `All ${totalFigures} <figure> element(s) have <figcaption>.`,\n 'All <figure> elements have a <figcaption>',\n `${figuresWithCaption}/${totalFigures} figures with captions`,\n );\n }\n\n if (majorityHaveCaptions) {\n return this.warn(\n `${figuresWithCaption}/${totalFigures} <figure> element(s) have <figcaption>.`,\n 'All <figure> elements have a <figcaption>',\n `${figuresWithCaption}/${totalFigures} figures with captions`,\n {\n priority: 'medium',\n description:\n 'AI agents use <figcaption> to understand the purpose and context of figures beyond what alt text provides. Without captions, agents treat figures as opaque image containers with no semantic meaning, missing opportunities to cite your visual data in AI-generated answers.',\n code: '<figure>\\n <img src=\"diagram.png\" alt=\"Architecture diagram\">\\n <figcaption>System architecture showing the three main components.</figcaption>\\n</figure>',\n },\n );\n }\n\n return this.fail(\n `${figuresWithCaption}/${totalFigures} <figure> element(s) have <figcaption>.`,\n 'All <figure> elements have a <figcaption>',\n `${figuresWithCaption}/${totalFigures} figures with captions`,\n {\n priority: 'medium',\n description:\n 'AI agents use <figcaption> to understand the purpose and context of figures beyond what alt text provides. Without captions, agents treat figures as opaque image containers with no semantic meaning, missing opportunities to cite your visual data in AI-generated answers.',\n code: '<figure>\\n <img src=\"diagram.png\" alt=\"Architecture diagram\">\\n <figcaption>System architecture showing the three main components.</figcaption>\\n</figure>',\n },\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class SkipNavAudit extends Audit {\n static override meta: AuditMeta = {\n id: '7.1',\n category: 'accessibility',\n title: 'Skip navigation link',\n failureTitle: 'Skip navigation link',\n description:\n 'Headless browser agents (Claude computer use, GPTBot with browser) parse the accessibility tree to navigate pages efficiently. A skip navigation link lets these agents jump directly to primary content without processing every nav element, reducing latency and improving content extraction accuracy.',\n scoreDisplayMode: 'binary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'Headless browser agents (Claude computer use, GPTBot) parse the accessibility tree to navigate pages. A skip navigation link lets agents jump directly to primary content without processing every nav element, reducing latency and improving content extraction accuracy.',\n fix: 'Add a \"Skip to main content\" link as the first focusable element in <body>, pointing to an anchor on your <main> element.',\n code: '<a href=\"#main-content\" class=\"skip-link\">Skip to main content</a>\\n<!-- ... navigation ... -->\\n<main id=\"main-content\">...</main>',\n effort: 'trivial',\n docsUrl: 'https://www.w3.org/WAI/WCAG21/Techniques/general/G1',\n tags: ['a11y', 'navigation', 'accessibility'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n if (!ctx.pages || ctx.pages.length === 0) {\n return this.warn(\n 'No pages scanned to check for skip navigation link.',\n 'A skip-to-content link among the first links in <body>',\n 'No pages scanned',\n );\n }\n\n for (const page of ctx.pages) {\n const $ = page.$;\n // Check the first few <a> elements in <body>\n const bodyLinks = $('body a').slice(0, 5);\n let found = false;\n\n bodyLinks.each((_, el) => {\n const text = $(el).text().toLowerCase().trim();\n const href = ($(el).attr('href') ?? '').toLowerCase();\n if (\n (text.includes('skip') || text.includes('jump to') || text.includes('go to main')) &&\n (href.includes('#main') || href.includes('#content') || href.includes('#skip'))\n ) {\n found = true;\n }\n });\n\n if (found) {\n return this.pass(\n 'Skip navigation link found among the first links in <body>.',\n 'A skip-to-content link among the first links in <body>',\n 'Skip navigation link detected',\n page.url,\n );\n }\n }\n\n return this.fail(\n 'No skip navigation link found. Screen reader and keyboard users rely on skip links to bypass repeated navigation.',\n 'A skip-to-content link among the first links in <body>',\n 'No skip navigation link detected in the first few <body> links',\n {\n priority: 'medium',\n description:\n 'Headless browser agents (Claude computer use, GPTBot with browser) parse the accessibility tree to navigate pages efficiently. A skip navigation link lets these agents jump directly to primary content without processing every nav element, reducing latency and improving content extraction accuracy.',\n code: '<a href=\"#main-content\" class=\"skip-link\">Skip to main content</a>\\n<!-- Then on your main content: -->\\n<main id=\"main-content\">...</main>',\n },\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext, PageContext } from '../../check-context';\n\nconst REQUIRED_LANDMARKS = [\n {\n name: 'banner/header',\n check: ($: PageContext['$']) => $('[role=\"banner\"]').length > 0 || $('header').length > 0,\n },\n {\n name: 'main',\n check: ($: PageContext['$']) => $('[role=\"main\"]').length > 0 || $('main').length > 0,\n },\n {\n name: 'navigation',\n check: ($: PageContext['$']) => $('[role=\"navigation\"]').length > 0 || $('nav').length > 0,\n },\n {\n name: 'contentinfo/footer',\n check: ($: PageContext['$']) => $('[role=\"contentinfo\"]').length > 0 || $('footer').length > 0,\n },\n];\n\nexport class AriaLandmarksAudit extends Audit {\n static override meta: AuditMeta = {\n id: '7.2',\n category: 'accessibility',\n title: 'ARIA landmarks complete',\n failureTitle: 'ARIA landmarks complete',\n description:\n 'Claude computer use and browser agents rely on ARIA landmarks to identify page regions (navigation, main content, footer). Missing landmarks force agents to guess page structure from raw HTML, leading to misclicked elements and incorrect content extraction.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'high',\n guidance: {\n impact:\n 'Claude computer use and browser agents rely on ARIA landmarks to identify page regions (navigation, main content, footer). Missing landmarks force agents to guess page structure from raw HTML, leading to misclicked elements and incorrect content extraction.',\n fix: 'Ensure your page has all four required landmarks: <header> (banner), <main>, <nav> (navigation), and <footer> (contentinfo). Use semantic HTML elements or ARIA roles.',\n code: '<header role=\"banner\">...</header>\\n<nav role=\"navigation\">...</nav>\\n<main role=\"main\">...</main>\\n<footer role=\"contentinfo\">...</footer>',\n effort: 'easy',\n docsUrl: 'https://www.w3.org/WAI/ARIA/apg/patterns/landmarks/',\n tags: ['a11y', 'aria', 'landmarks', 'accessibility'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n if (!ctx.pages || ctx.pages.length === 0) {\n return this.warn(\n 'No pages scanned to check ARIA landmarks.',\n 'Page has banner/header, main, navigation, and contentinfo/footer landmarks',\n 'No pages scanned',\n );\n }\n\n const $ = ctx.pages[0].$;\n const present: string[] = [];\n const missing: string[] = [];\n\n for (const landmark of REQUIRED_LANDMARKS) {\n if (landmark.check($)) {\n present.push(landmark.name);\n } else {\n missing.push(landmark.name);\n }\n }\n\n if (missing.length === 0) {\n return this.pass(\n 'All required ARIA landmarks are present.',\n 'Page has banner/header, main, navigation, and contentinfo/footer landmarks',\n `Present: ${present.join(', ')}`,\n ctx.pages[0].url,\n );\n }\n\n if (missing.length <= 1) {\n return this.warn(\n `Missing ARIA landmarks: ${missing.join(', ')}. Landmarks help assistive technologies and AI agents understand page structure.`,\n 'Page has banner/header, main, navigation, and contentinfo/footer landmarks',\n `Present: ${present.join(', ')}; Missing: ${missing.join(', ')}`,\n {\n priority: 'high',\n description: `Claude computer use and browser agents rely on ARIA landmarks to identify page regions (navigation, main content, footer). Missing landmarks (${missing.join(', ')}) force agents to guess page structure from raw HTML, leading to misclicked elements and incorrect content extraction.`,\n code: missing\n .map((m) => {\n if (m === 'banner/header') return '<header role=\"banner\">...</header>';\n if (m === 'main') return '<main role=\"main\">...</main>';\n if (m === 'navigation') return '<nav role=\"navigation\">...</nav>';\n return '<footer role=\"contentinfo\">...</footer>';\n })\n .join('\\n'),\n },\n ctx.pages[0].url,\n );\n }\n\n return this.fail(\n `Missing ARIA landmarks: ${missing.join(', ')}. Landmarks help assistive technologies and AI agents understand page structure.`,\n 'Page has banner/header, main, navigation, and contentinfo/footer landmarks',\n `Present: ${present.join(', ')}; Missing: ${missing.join(', ')}`,\n {\n priority: 'high',\n description: `Claude computer use and browser agents rely on ARIA landmarks to identify page regions (navigation, main content, footer). Missing landmarks (${missing.join(', ')}) force agents to guess page structure from raw HTML, leading to misclicked elements and incorrect content extraction.`,\n code: missing\n .map((m) => {\n if (m === 'banner/header') return '<header role=\"banner\">...</header>';\n if (m === 'main') return '<main role=\"main\">...</main>';\n if (m === 'navigation') return '<nav role=\"navigation\">...</nav>';\n return '<footer role=\"contentinfo\">...</footer>';\n })\n .join('\\n'),\n },\n ctx.pages[0].url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class NavAriaLabelAudit extends Audit {\n static override meta: AuditMeta = {\n id: '7.3',\n category: 'accessibility',\n title: '<nav> has aria-label',\n failureTitle: '<nav> has aria-label',\n description:\n 'AI browser agents use aria-label on <nav> elements to understand navigation purpose before interacting with it. Unlabeled navs force agents to inspect child links to guess whether it is main navigation, breadcrumbs, or a footer menu, slowing down agentic workflows.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'AI browser agents use aria-label on <nav> elements to understand navigation purpose before interacting with it. Unlabeled navs force agents to inspect child links to guess the navigation type, slowing down agentic workflows.',\n fix: 'Add an aria-label attribute to every <nav> element describing its purpose (e.g., \"Main navigation\", \"Breadcrumb\", \"Footer navigation\").',\n code: '<nav aria-label=\"Main navigation\">...</nav>',\n effort: 'trivial',\n docsUrl: 'https://www.w3.org/WAI/ARIA/apg/patterns/landmarks/',\n tags: ['a11y', 'aria', 'navigation', 'accessibility'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n if (!ctx.pages || ctx.pages.length === 0) {\n return this.warn(\n 'No pages scanned to check <nav> aria-labels.',\n 'All <nav> elements have aria-label attribute',\n 'No pages scanned',\n );\n }\n\n const $ = ctx.pages[0].$;\n const navs = $('nav');\n\n if (navs.length === 0) {\n return this.warn(\n 'No <nav> elements found on page. Navigation should use semantic <nav> elements.',\n 'All <nav> elements have aria-label attribute',\n 'No <nav> elements on page',\n {\n priority: 'medium',\n description:\n 'AI browser agents rely on <nav> landmarks to locate and understand site navigation. Without <nav> elements, agents must scan the full DOM to find navigation links, which is slower and less reliable. Wrap your navigation in <nav> with an aria-label.',\n code: '<nav aria-label=\"Main navigation\">...</nav>',\n },\n ctx.pages[0].url,\n );\n }\n\n let labeled = 0;\n let unlabeled = 0;\n\n navs.each((_, el) => {\n const ariaLabel = $(el).attr('aria-label');\n const ariaLabelledby = $(el).attr('aria-labelledby');\n if ((ariaLabel && ariaLabel.trim()) || (ariaLabelledby && ariaLabelledby.trim())) {\n labeled++;\n } else {\n unlabeled++;\n }\n });\n\n if (unlabeled === 0) {\n return this.pass(\n `All ${labeled} <nav> element(s) have aria-label or aria-labelledby.`,\n 'All <nav> elements have aria-label attribute',\n `${labeled} <nav> element(s), all labeled`,\n ctx.pages[0].url,\n );\n }\n\n const recommendation = {\n priority: 'medium' as const,\n description:\n 'AI browser agents use aria-label on <nav> elements to understand navigation purpose before interacting with it. Unlabeled navs force agents to inspect child links to guess whether it is main navigation, breadcrumbs, or a footer menu, slowing down agentic workflows.',\n code: '<nav aria-label=\"Main navigation\">...</nav>',\n };\n\n if (labeled / navs.length >= 0.5) {\n return this.warn(\n `${unlabeled} of ${navs.length} <nav> element(s) lack aria-label. Navigation elements need labels for screen readers and AI agents.`,\n 'All <nav> elements have aria-label attribute',\n `${unlabeled} of ${navs.length} <nav> element(s) missing aria-label`,\n recommendation,\n ctx.pages[0].url,\n );\n }\n\n return this.fail(\n `${unlabeled} of ${navs.length} <nav> element(s) lack aria-label. Navigation elements need labels for screen readers and AI agents.`,\n 'All <nav> elements have aria-label attribute',\n `${unlabeled} of ${navs.length} <nav> element(s) missing aria-label`,\n recommendation,\n ctx.pages[0].url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class FormErrorMessagesAudit extends Audit {\n static override meta: AuditMeta = {\n id: '7.6',\n category: 'accessibility',\n title: 'Form error messages linked',\n failureTitle: 'Form error messages linked',\n description:\n 'AI agents filling forms use aria-describedby to detect and understand validation errors programmatically. Without linked error messages, agents cannot self-correct form submissions, causing them to repeatedly submit invalid data or abandon the form entirely.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'AI agents filling forms use aria-describedby to detect and understand validation errors programmatically. Without linked error messages, agents cannot self-correct form submissions, causing them to repeatedly submit invalid data or abandon the form entirely.',\n fix: 'Add aria-describedby attributes to form inputs that link to error message elements. Use role=\"alert\" on error message containers for dynamic error display.',\n code: '<input id=\"email\" aria-describedby=\"email-error\">\\n<span id=\"email-error\" role=\"alert\">Please enter a valid email.</span>',\n effort: 'easy',\n docsUrl: 'https://www.w3.org/WAI/WCAG21/Techniques/aria/ARIA1',\n tags: ['a11y', 'forms', 'aria', 'accessibility'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n if (!ctx.pages || ctx.pages.length === 0) {\n return this.notApplicable(\n 'No pages scanned — nothing to evaluate (excluded from score).',\n 'Form inputs use aria-describedby to link to error messages',\n 'No pages scanned',\n );\n }\n\n let totalFormInputs = 0;\n let withDescribedby = 0;\n\n for (const page of ctx.pages) {\n const $ = page.$;\n const formInputs = $('form input, form select, form textarea');\n\n formInputs.each((_, el) => {\n const type = ($(el).attr('type') ?? '').toLowerCase();\n if (type === 'hidden' || type === 'submit' || type === 'button') return;\n totalFormInputs++;\n const describedbyIds = $(el).attr('aria-describedby');\n if (describedbyIds) {\n // Verify at least one referenced ID actually exists in the DOM\n const ids = describedbyIds.split(/\\s+/).filter(Boolean);\n const hasValidRef = ids.some((id) => $(`[id=\"${id.replace(/\"/g, '\\\\\"')}\"]`).length > 0);\n if (hasValidRef) {\n withDescribedby++;\n }\n }\n });\n }\n\n if (totalFormInputs === 0) {\n return this.notApplicable(\n 'No form inputs found — no forms to validate (excluded from score).',\n 'Form inputs use aria-describedby to link to error messages',\n 'No form inputs on scanned pages',\n );\n }\n\n if (withDescribedby > 0) {\n return this.pass(\n `${withDescribedby} of ${totalFormInputs} form input(s) use aria-describedby for error message linking.`,\n 'Form inputs use aria-describedby to link to error messages',\n `${withDescribedby} of ${totalFormInputs} input(s) have aria-describedby`,\n );\n }\n\n return this.warn(\n 'No form inputs use aria-describedby. Error messages should be programmatically linked to their inputs.',\n 'Form inputs use aria-describedby to link to error messages',\n `${totalFormInputs} form input(s), none with aria-describedby`,\n {\n priority: 'medium',\n description:\n 'AI agents filling forms use aria-describedby to detect and understand validation errors programmatically. Without linked error messages, agents cannot self-correct form submissions, causing them to repeatedly submit invalid data or abandon the form entirely.',\n code: '<input id=\"email\" aria-describedby=\"email-error\">\\n<span id=\"email-error\" role=\"alert\">Please enter a valid email.</span>',\n },\n );\n }\n}\n","/**\n * Accessibility audits, backed by our vendored a11y rule engine (ported from\n * axe-core v4.12.1; see ./engine).\n *\n * Each audit wraps one or more a11y rules (run over jsdom in the\n * orchestrator and cached on each PageContext as `a11yResults`). We only adopt\n * rules that describe how an AI agent reads/acts on a page through the\n * accessibility tree — roles, programmatic names, ARIA relationships, document\n * structure. Human-perception rules (color contrast, focus visibility, target\n * size, reduced motion) are deliberately excluded: a non-human consumer can't\n * perceive them.\n *\n * Aggregation across the scanned pages, per audit:\n * - any constituent rule FAILS on any page → fail (with selectors)\n * - else any rule is INCOMPLETE (needs review) → warn\n * - else any rule PASSES → pass\n * - else every rule was INAPPLICABLE / unseen → na (nothing to assess)\n */\nimport type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\nimport type { A11yStatus } from './runner';\n\ninterface A11yAuditSpec {\n meta: AuditMeta;\n /** a11y rule ids whose failure should fail this audit. */\n rules: string[];\n}\n\n/** Base class: aggregates this audit's a11y rules across all scanned pages. */\nabstract class A11yBackedAudit extends Audit {\n protected abstract rules: string[];\n\n audit(ctx: CheckContext): AuditResult {\n const meta = (this.constructor as typeof Audit).meta;\n const expected = `accessibility rules pass: ${this.rules.join(', ')}`;\n\n let sawFail = false;\n let sawIncomplete = false;\n let sawPass = false;\n const failings: string[] = [];\n let failPage: string | undefined;\n\n for (const p of ctx.pages) {\n const results = p.a11yResults;\n if (!results) continue;\n for (const ruleId of this.rules) {\n const r = results[ruleId];\n if (!r) continue;\n if (r.status === ('fail' as A11yStatus)) {\n sawFail = true;\n failPage ??= p.url;\n for (const n of r.nodes) {\n if (failings.length < 5) failings.push(n.target);\n }\n } else if (r.status === ('incomplete' as A11yStatus)) {\n sawIncomplete = true;\n } else if (r.status === ('pass' as A11yStatus)) {\n sawPass = true;\n }\n }\n }\n\n if (sawFail) {\n const found = `Failing element(s): ${failings.join('; ') || 'see report'}`;\n return this.fail(\n `${meta.failureTitle} — accessibility violations found.`,\n expected,\n found,\n { priority: meta.defaultPriority, description: meta.description, code: meta.guidance?.code },\n failPage,\n );\n }\n if (sawIncomplete && !sawPass) {\n return this.warn(\n `${meta.title} — accessibility checks could not fully determine; manual review advised.`,\n expected,\n 'Incomplete (needs review)',\n meta.defaultPriority,\n );\n }\n if (sawPass) {\n return this.pass(`${meta.title} — accessibility checks pass.`, expected, 'No violations');\n }\n return this.notApplicable(\n `${meta.title} — no applicable elements on scanned pages.`,\n expected,\n 'Not applicable',\n );\n }\n}\n\n/** All a11y rule ids the adopted audits depend on (fed to the orchestrator). */\nexport const A11Y_RULES: string[] = [];\n\nfunction defineA11yAudit(spec: A11yAuditSpec): typeof Audit {\n /* v8 ignore next */\n for (const r of spec.rules) if (!A11Y_RULES.includes(r)) A11Y_RULES.push(r);\n return class extends A11yBackedAudit {\n static override meta = spec.meta;\n protected rules = spec.rules;\n } as unknown as typeof Audit;\n}\n\nconst base = {\n category: 'accessibility' as const,\n scoreDisplayMode: 'binary' as const,\n weight: 1.0,\n};\n\n// ── 7.4 Landmarks are uniquely identifiable ─────────────────────\n// Replaces the former hand-rolled MultipleNavAudit. axe `landmark-unique`\n// covers all landmark types (not just <nav>) by role + accessible-name.\nexport const A11yLandmarkUniqueAudit = defineA11yAudit({\n rules: ['landmark-unique'],\n meta: {\n ...base,\n id: '7.4',\n title: 'Landmarks are uniquely identifiable',\n failureTitle: 'Duplicate landmarks without distinguishing labels',\n description:\n 'AI browser agents traverse the accessibility tree and use a landmark’s role plus accessible name to target the right region. Two landmarks of the same role (e.g. two <nav>s) without unique labels are indistinguishable, causing agents to act on the wrong region.',\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'Without unique role/label combinations, agents cannot tell primary navigation from footer or breadcrumb navigation, leading to navigation failures.',\n fix: 'Give each landmark of the same role a unique aria-label or aria-labelledby (e.g. \"Primary navigation\", \"Footer navigation\").',\n code: '<nav aria-label=\"Primary navigation\">...</nav>\\n<nav aria-label=\"Footer navigation\">...</nav>',\n effort: 'trivial',\n tags: ['aria', 'landmarks', 'navigation', 'agent'],\n },\n },\n});\n\n// ── 7.5 Form inputs have associated labels ──────────────────────\n// Replaces the former hand-rolled FormLabelsAudit.\nexport const A11yFormLabelsAudit = defineA11yAudit({\n rules: ['label', 'select-name'],\n meta: {\n ...base,\n id: '7.5',\n title: 'Form inputs have associated labels',\n failureTitle: 'Form inputs lack associated labels',\n description:\n 'AI agents filling forms identify fields by their accessible name (label, aria-label, or aria-labelledby). Unlabeled inputs are invisible to form-filling agents, so automated workflows like \"sign me up\" or \"submit a contact request\" fail.',\n defaultPriority: 'high',\n guidance: {\n impact:\n 'Unlabeled inputs have no programmatic name, so form-filling agents cannot map fields to data and abandon or misfill the form.',\n fix: 'Associate every input/select/textarea with a <label for=\"id\">, or add aria-label/aria-labelledby. Hidden and button-type inputs are exempt.',\n code: '<label for=\"email\">Email</label>\\n<input id=\"email\" type=\"email\" name=\"email\">',\n effort: 'easy',\n tags: ['forms', 'aria', 'agent'],\n },\n },\n});\n\n// ── 7.7 Buttons and links have accessible names ─────────────────\n// Replaces the former hand-rolled AccessibleNamesAudit AND IconLabelsAudit\n// (icon-only controls are just buttons/links with no visible text, already\n// covered by these rules).\nexport const A11yAccessibleNamesAudit = defineA11yAudit({\n rules: ['button-name', 'link-name'],\n meta: {\n ...base,\n id: '7.7',\n title: 'Buttons and links have accessible names',\n failureTitle: 'Buttons or links without accessible names',\n description:\n 'AI browser agents identify clickable elements by their accessible name in the accessibility tree. Buttons and links (including icon-only controls) without text, aria-label, or aria-labelledby are invisible to agents, so they cannot navigate the site or trigger actions.',\n defaultPriority: 'high',\n guidance: {\n impact:\n 'An unnamed button or link is an unidentifiable action target, causing failed or wrong interactions in agentic workflows.',\n fix: 'Give every <button> and <a> text content, aria-label, or aria-labelledby. For icon-only controls, use aria-label to describe the action.',\n code: '<a href=\"/pricing\" aria-label=\"Go to pricing page\">...</a>\\n<button aria-label=\"Close menu\">X</button>',\n effort: 'easy',\n tags: ['aria', 'interactive', 'agent'],\n },\n },\n});\n\n// ── 7.9 Dialogs have accessible names ───────────────────────────\n// Replaces the former hand-rolled ModalDialogAudit.\nexport const A11yDialogNameAudit = defineA11yAudit({\n rules: ['aria-dialog-name'],\n meta: {\n ...base,\n id: '7.9',\n title: 'Dialogs have accessible names',\n failureTitle: 'Dialogs without accessible names',\n description:\n 'AI browser agents detect modals via role=\"dialog\"/\"alertdialog\" and need an accessible name to understand the dialog’s purpose. Unlabeled dialogs trap agents in unknown UI states, blocking confirmations, forms, or cookie-consent flows.',\n defaultPriority: 'high',\n guidance: {\n impact:\n 'An unlabeled dialog gives an agent no context for the interruption, so it cannot decide how to proceed.',\n fix: 'Add aria-labelledby (pointing to the dialog title) or aria-label to every role=\"dialog\"/\"alertdialog\" element. Prefer the native <dialog> element.',\n code: '<div role=\"dialog\" aria-labelledby=\"dlg-title\">\\n <h2 id=\"dlg-title\">Confirm action</h2>\\n</div>',\n effort: 'easy',\n tags: ['aria', 'dialog', 'agent'],\n },\n },\n});\n\n// ── 7.10 Page exposed to the accessibility tree ─────────────────\nexport const A11yAriaHiddenBodyAudit = defineA11yAudit({\n rules: ['aria-hidden-body'],\n meta: {\n ...base,\n id: '7.10',\n title: 'Page exposed to the accessibility tree',\n failureTitle: 'Page hidden from the accessibility tree',\n description:\n 'aria-hidden=\"true\" on the document body removes the entire page from the accessibility tree. AI browser agents that navigate via the accessibility tree would see nothing at all.',\n defaultPriority: 'critical',\n guidance: {\n impact:\n 'If the root is aria-hidden, agents relying on the accessibility tree perceive an empty page and cannot read or act on any content.',\n fix: 'Never put aria-hidden=\"true\" on <body> or the root element. Hide only specific decorative subtrees.',\n code: '<!-- BAD --> <body aria-hidden=\"true\">\\n<!-- GOOD --> <body> ... </body>',\n effort: 'trivial',\n tags: ['aria', 'accessibility-tree', 'agent'],\n },\n },\n});\n\n// ── 7.11 Valid ARIA roles ───────────────────────────────────────\nexport const A11yAriaRolesAudit = defineA11yAudit({\n rules: ['aria-roles', 'aria-deprecated-role', 'aria-allowed-role'],\n meta: {\n ...base,\n id: '7.11',\n title: 'Valid ARIA roles',\n failureTitle: 'Invalid or misused ARIA roles',\n description:\n 'AI agents map elements to behaviors by their ARIA role. Invalid, deprecated, or disallowed roles make an element’s purpose ambiguous, so agents may mis-classify or skip it.',\n defaultPriority: 'high',\n guidance: {\n impact:\n 'A wrong role tells an agent the element is something it is not (e.g. a div role=\"button\" that isn’t operable), causing failed or incorrect actions.',\n fix: 'Use valid, non-deprecated ARIA roles allowed on the element. Prefer native HTML elements over role overrides.',\n code: '<button>Add to cart</button> <!-- preferred over <div role=\"button\"> -->',\n effort: 'easy',\n tags: ['aria', 'roles', 'agent'],\n },\n },\n});\n\n// ── 7.12 Valid ARIA attributes ──────────────────────────────────\nexport const A11yAriaAttributesAudit = defineA11yAudit({\n rules: ['aria-valid-attr', 'aria-valid-attr-value', 'aria-allowed-attr', 'aria-prohibited-attr'],\n meta: {\n ...base,\n id: '7.12',\n title: 'Valid ARIA attributes',\n failureTitle: 'Invalid ARIA attributes or values',\n description:\n 'ARIA states and properties carry the machine-readable state agents act on (expanded, checked, disabled, labels). Invalid attributes or values corrupt that state.',\n defaultPriority: 'high',\n guidance: {\n impact:\n 'Misspelled attributes or bad values (e.g. aria-expanded=\"yes\") leave agents with wrong or missing state, leading to incorrect interactions.',\n fix: 'Use only valid aria-* attributes with valid values, allowed on the element’s role.',\n code: '<button aria-expanded=\"false\" aria-controls=\"menu\">Menu</button>',\n effort: 'easy',\n tags: ['aria', 'attributes', 'agent'],\n },\n },\n});\n\n// ── 7.13 Complete ARIA relationships ────────────────────────────\nexport const A11yAriaRelationshipsAudit = defineA11yAudit({\n rules: ['aria-required-attr', 'aria-required-children', 'aria-required-parent'],\n meta: {\n ...base,\n id: '7.13',\n title: 'Complete ARIA relationships',\n failureTitle: 'Incomplete ARIA role relationships',\n description:\n 'Composite widgets (menus, listboxes, tabs, grids) require specific child/parent roles and attributes. Missing pieces break the structure agents traverse.',\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'An incomplete widget (e.g. a role=\"listbox\" without role=\"option\" children) is unparseable as a coherent control, so agents cannot operate it reliably.',\n fix: 'Provide all required attributes and the required child/parent roles for each ARIA widget.',\n code: '<ul role=\"listbox\"><li role=\"option\">A</li><li role=\"option\">B</li></ul>',\n effort: 'moderate',\n tags: ['aria', 'relationships', 'agent'],\n },\n },\n});\n\n// ── 7.14 Unique IDs for references ──────────────────────────────\nexport const A11yDuplicateIdAudit = defineA11yAudit({\n rules: ['duplicate-id-aria'],\n meta: {\n ...base,\n id: '7.14',\n title: 'Unique IDs for ARIA references',\n failureTitle: 'Duplicate IDs break ARIA references',\n description:\n 'aria-labelledby / aria-describedby / for resolve by id. Duplicate ids make resolution ambiguous, so an agent may read the wrong label or description.',\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'Duplicate ids referenced by ARIA cause agents to associate the wrong text with a control, mislabeling actions.',\n fix: 'Ensure every id referenced by ARIA/label is unique within the page.',\n code: '<label id=\"lbl-email\">Email</label><input aria-labelledby=\"lbl-email\">',\n effort: 'easy',\n tags: ['aria', 'ids', 'agent'],\n },\n },\n});\n\n// ── 7.15 Form fields declare autocomplete ───────────────────────\nexport const A11yAutocompleteAudit = defineA11yAudit({\n rules: ['autocomplete-valid'],\n meta: {\n ...base,\n id: '7.15',\n title: 'Form fields use valid autocomplete tokens',\n failureTitle: 'Invalid autocomplete tokens on form fields',\n description:\n 'Form-filling agents map fields to known data (name, email, address, payment) via autocomplete tokens. Invalid tokens break that mapping.',\n defaultPriority: 'high',\n guidance: {\n impact:\n 'Without valid autocomplete, an agent must guess each field’s meaning, so automated checkout/sign-up flows fail or misfill.',\n fix: 'Use valid HTML autocomplete tokens on inputs (e.g. email, given-name, postal-code, cc-number).',\n code: '<input name=\"email\" autocomplete=\"email\">',\n effort: 'easy',\n tags: ['forms', 'autocomplete', 'agent'],\n },\n },\n});\n\n// ── 7.16 No nested interactive controls ─────────────────────────\nexport const A11yNestedInteractiveAudit = defineA11yAudit({\n rules: ['nested-interactive'],\n meta: {\n ...base,\n id: '7.16',\n title: 'No nested interactive controls',\n failureTitle: 'Nested interactive controls',\n description:\n 'Interactive elements nested inside other interactive elements (e.g. a button inside a link) create ambiguous targets in the accessibility tree.',\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'Nested controls give agents two overlapping action targets, so the wrong action may fire or the control becomes unoperable.',\n fix: 'Do not nest focusable/interactive elements; keep one control per actionable region.',\n code: '<!-- BAD --> <a href=\"/x\"><button>Go</button></a>',\n effort: 'moderate',\n tags: ['interactive', 'agent'],\n },\n },\n});\n\n// ── 7.17 Data tables have header associations ───────────────────\nexport const A11yTableHeadersAudit = defineA11yAudit({\n rules: ['td-has-header', 'th-has-data-cells', 'td-headers-attr', 'scope-attr-valid'],\n meta: {\n ...base,\n id: '7.17',\n title: 'Data tables have header associations',\n failureTitle: 'Data table cells lack header associations',\n description:\n 'Agents extracting tabular data rely on header↔cell associations (th scope / headers attr) to know what each value means. Missing associations make tables ambiguous.',\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'Without header associations, an agent reading a price/spec table cannot reliably pair each value with its column/row meaning.',\n fix: 'Use <th scope=\"col\"|\"row\"> headers (or headers/id) so every data cell maps to its header.',\n code: '<table><tr><th scope=\"col\">Size</th><th scope=\"col\">Price</th></tr><tr><td>M</td><td>$29</td></tr></table>',\n effort: 'moderate',\n tags: ['tables', 'extraction', 'agent'],\n },\n },\n});\n\n// ── 7.18 Page has a title ───────────────────────────────────────\nexport const A11yDocumentTitleAudit = defineA11yAudit({\n rules: ['document-title'],\n meta: {\n ...base,\n id: '7.18',\n title: 'Page has a non-empty <title>',\n failureTitle: 'Missing or empty <title>',\n description:\n 'The document title is the page’s identity in the accessibility tree and in agent context windows. A missing/empty title leaves the page unnamed.',\n defaultPriority: 'high',\n guidance: {\n impact:\n 'Agents use <title> to identify and reference a page; without it, the page is hard to cite or disambiguate.',\n fix: 'Provide a descriptive, unique <title> for every page.',\n code: '<title>Men’s Wool Runners — Allbirds</title>',\n effort: 'trivial',\n tags: ['title', 'identity', 'agent'],\n },\n },\n});\n\n// ── 7.19 Frames are titled ──────────────────────────────────────\nexport const A11yFrameTitleAudit = defineA11yAudit({\n rules: ['frame-title', 'frame-title-unique'],\n meta: {\n ...base,\n id: '7.19',\n title: 'Frames are titled',\n failureTitle: 'Untitled or duplicate-titled frames',\n description:\n 'Agents need a title to understand what each iframe contains. Untitled or duplicate-titled frames are opaque embedded contexts.',\n defaultPriority: 'low',\n guidance: {\n impact:\n 'Without a title an agent cannot tell what an iframe holds (checkout widget? map? video?), so it may skip or misuse it.',\n fix: 'Give every <iframe> a unique, descriptive title attribute.',\n code: '<iframe title=\"Checkout payment form\" src=\"...\"></iframe>',\n effort: 'easy',\n tags: ['frames', 'agent'],\n },\n },\n});\n\n// ── 7.20 No auto-refresh / time-based redirect ──────────────────\nexport const A11yMetaRefreshAudit = defineA11yAudit({\n rules: ['meta-refresh'],\n meta: {\n ...base,\n id: '7.20',\n title: 'No time-based auto-refresh/redirect',\n failureTitle: 'Time-based meta refresh present',\n description:\n 'A <meta http-equiv=\"refresh\"> that reloads/redirects after a delay disrupts an agent mid-read and can trap it in unexpected navigation.',\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'Auto-refresh changes the page out from under an agent that is reading or acting, corrupting its state and any in-progress task.',\n fix: 'Remove time-based meta refresh; use proper server redirects (3xx) for instant redirects.',\n code: '<!-- BAD --> <meta http-equiv=\"refresh\" content=\"5;url=/next\">',\n effort: 'easy',\n tags: ['navigation', 'agent'],\n },\n },\n});\n\n// ── 7.21 Logical focus order ────────────────────────────────────\nexport const A11yTabindexAudit = defineA11yAudit({\n rules: ['tabindex'],\n meta: {\n ...base,\n id: '7.21',\n title: 'No positive tabindex (logical focus order)',\n failureTitle: 'Positive tabindex disrupts focus order',\n description:\n 'Positive tabindex values force a non-DOM focus order. Agents that traverse the page by focus order then encounter a confusing, non-linear sequence.',\n defaultPriority: 'low',\n guidance: {\n impact:\n 'A scrambled focus order makes sequential agent navigation jump around unpredictably, raising the chance of missed or wrong interactions.',\n fix: 'Avoid tabindex > 0; rely on DOM order and use tabindex=\"0\"/\"-1\" only.',\n code: '<!-- BAD --> <input tabindex=\"5\"> <!-- GOOD --> <input>',\n effort: 'moderate',\n tags: ['focus-order', 'agent'],\n },\n },\n});\n\n// ── 7.22 No deprecated presentational elements ──────────────────\nexport const A11yDeprecatedElementsAudit = defineA11yAudit({\n rules: ['marquee', 'blink'],\n meta: {\n ...base,\n id: '7.22',\n title: 'No deprecated presentational elements',\n failureTitle: 'Deprecated <marquee>/<blink> elements',\n description:\n 'Deprecated elements like <marquee> and <blink> have undefined semantics and unstable text content for parsers.',\n defaultPriority: 'low',\n guidance: {\n impact:\n 'Animated/deprecated elements produce unstable or meaningless content for an agent parsing the DOM.',\n fix: 'Remove <marquee>/<blink>; use semantic HTML + CSS if motion is needed.',\n code: '<!-- Remove --> <marquee>...</marquee>',\n effort: 'easy',\n tags: ['deprecated', 'agent'],\n },\n },\n});\n\n// ── 7.23 No presentation-role conflicts ─────────────────────────\nexport const A11yPresentationConflictAudit = defineA11yAudit({\n rules: ['presentation-role-conflict'],\n meta: {\n ...base,\n id: '7.23',\n title: 'No presentation-role conflicts',\n failureTitle: 'Presentation role conflicts with focusable/labeled element',\n description:\n 'An element marked role=\"presentation\"/\"none\" while still focusable or carrying ARIA sends contradictory signals about whether it exists in the accessibility tree.',\n defaultPriority: 'low',\n guidance: {\n impact:\n 'A presentational element that is still focusable/labeled confuses agents about whether to treat it as content or ignore it.',\n fix: 'Don’t put role=\"presentation\"/\"none\" on focusable or ARIA-labeled elements.',\n code: '<!-- BAD --> <a href=\"/x\" role=\"presentation\">Link</a>',\n effort: 'easy',\n tags: ['aria', 'agent'],\n },\n },\n});\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class HttpsEnabledAudit extends Audit {\n static override meta: AuditMeta = {\n id: '8.1',\n category: 'technical-readiness',\n title: 'HTTPS enabled',\n failureTitle: 'HTTPS enabled',\n description:\n 'Enterprise AI frameworks refuse to interact with non-HTTPS sites due to security policies. GPTBot, ClaudeBot, and enterprise RAG systems all skip HTTP-only sites entirely, making your content invisible to AI-generated answers. Enable HTTPS with a valid TLS certificate.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'critical',\n guidance: {\n impact:\n 'HTTP-only sites are completely excluded from all major AI systems. GPTBot, ClaudeBot, Perplexity, and enterprise RAG pipelines refuse to connect to non-HTTPS origins due to security policies. Your entire site is invisible to AI-generated answers, product recommendations, and agentic workflows.',\n fix: \"Enable HTTPS by obtaining a TLS certificate (free via Let's Encrypt) and configuring your web server to serve all traffic over HTTPS. Set up a 301 redirect from HTTP to HTTPS to ensure all traffic is encrypted.\",\n code: \"# Certbot (Let's Encrypt) quick setup:\\nsudo certbot --nginx -d yoursite.com -d www.yoursite.com\\n\\n# Nginx HTTPS config:\\nserver {\\n listen 443 ssl;\\n ssl_certificate /etc/letsencrypt/live/yoursite.com/fullchain.pem;\\n ssl_certificate_key /etc/letsencrypt/live/yoursite.com/privkey.pem;\\n}\",\n effort: 'easy',\n docsUrl: 'https://letsencrypt.org/getting-started/',\n tags: ['security', 'https', 'critical'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const isHttps = ctx.baseUrl.startsWith('https://');\n const page = ctx.pages?.[0];\n const status200 = page?.fetchResult.status === 200;\n\n if (isHttps && status200) {\n return this.pass(\n 'Site is served over HTTPS with a valid TLS connection.',\n 'Base URL uses https:// and homepage returns 200',\n `${ctx.baseUrl} — status ${page?.fetchResult.status}`,\n page?.url,\n );\n }\n\n if (isHttps && !status200) {\n return this.warn(\n `Site uses HTTPS but homepage returned status ${page?.fetchResult.status ?? 'unknown'}. Possible TLS or server error.`,\n 'Base URL uses https:// and homepage returns 200',\n `${ctx.baseUrl} — status ${page?.fetchResult.status ?? 'N/A'}`,\n {\n priority: 'high',\n description:\n 'Enterprise AI frameworks refuse to interact with sites that have TLS errors. A non-200 HTTPS response prevents AI agents from ingesting your content, effectively making your site invisible to all AI systems. Fix server or TLS configuration to return a clean 200.',\n code: '# Verify TLS with: curl -vI https://yoursite.com\\n# Check for certificate expiry, chain issues, or redirect loops',\n },\n page?.url,\n );\n }\n\n return this.fail(\n 'Site is not served over HTTPS. AI agents require secure connections.',\n 'Base URL uses https:// and homepage returns 200',\n `Base URL: ${ctx.baseUrl}`,\n {\n priority: 'critical',\n description:\n 'Enterprise AI frameworks refuse to interact with non-HTTPS sites due to security policies. GPTBot, ClaudeBot, and enterprise RAG systems all skip HTTP-only sites entirely, making your content invisible to AI-generated answers. Enable HTTPS with a valid TLS certificate.',\n code: '# For nginx:\\nserver {\\n listen 443 ssl;\\n ssl_certificate /path/to/cert.pem;\\n ssl_certificate_key /path/to/key.pem;\\n}',\n },\n page?.url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class HstsHeaderAudit extends Audit {\n static override meta: AuditMeta = {\n id: '8.2',\n category: 'technical-readiness',\n title: 'HSTS header',\n failureTitle: 'HSTS header',\n description:\n 'AI agents that follow redirects from HTTP to HTTPS waste time on the redirect hop and may be blocked by strict security policies that reject non-HSTS sites. HSTS ensures agents always connect over HTTPS on the first request, improving crawl efficiency and trust scoring.',\n scoreDisplayMode: 'binary',\n weight: 1.0,\n defaultPriority: 'high',\n guidance: {\n impact:\n 'Without HSTS, AI agents that first connect over HTTP must follow a redirect to HTTPS, wasting a round-trip on every new connection. Worse, strict enterprise AI security policies may reject non-HSTS sites outright, blocking your content from enterprise RAG pipelines and AI-powered procurement tools.',\n fix: 'Add the Strict-Transport-Security header to your HTTPS responses. Use a max-age of at least one year (31536000 seconds), include subdomains, and add the preload directive to be included in browser preload lists.',\n code: 'Strict-Transport-Security: max-age=31536000; includeSubDomains; preload',\n effort: 'trivial',\n docsUrl:\n 'https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security',\n tags: ['security', 'headers', 'https'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const page = ctx.pages?.[0];\n const headers = page?.fetchResult.headers ?? {};\n const hsts = headers['strict-transport-security'];\n\n if (hsts) {\n return this.pass(\n `Strict-Transport-Security header is present: ${hsts}`,\n 'Strict-Transport-Security header present on homepage response',\n `strict-transport-security: ${hsts}`,\n page?.url,\n );\n }\n\n return this.fail(\n 'Strict-Transport-Security header is missing from the homepage response.',\n 'Strict-Transport-Security header present on homepage response',\n 'Header not found',\n {\n priority: 'high',\n description:\n 'AI agents that follow redirects from HTTP to HTTPS waste time on the redirect hop and may be blocked by strict security policies that reject non-HSTS sites. HSTS ensures agents always connect over HTTPS on the first request, improving crawl efficiency and trust scoring.',\n code: 'Strict-Transport-Security: max-age=31536000; includeSubDomains; preload',\n },\n page?.url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class CspHeaderAudit extends Audit {\n static override meta: AuditMeta = {\n id: '8.3',\n category: 'technical-readiness',\n title: 'Content-Security-Policy header',\n failureTitle: 'Content-Security-Policy header',\n description:\n \"AI trust-scoring systems check for CSP headers as a signal of site security maturity. Sites without CSP are flagged as potentially compromised, which can reduce your content's trust score in AI-generated recommendations. CSP also prevents injected scripts from altering the content AI agents crawl.\",\n scoreDisplayMode: 'binary',\n weight: 1.0,\n defaultPriority: 'high',\n guidance: {\n impact:\n 'AI trust-scoring systems treat a missing Content-Security-Policy as a sign of weak security posture. Sites without CSP are vulnerable to XSS attacks that can inject malicious content into the pages AI agents crawl, poisoning AI knowledge bases with attacker-controlled text. This lowers your trust score and may cause AI systems to deprioritize or exclude your content from recommendations.',\n fix: 'Add a Content-Security-Policy header to your server responses. Start with a restrictive policy that only allows resources from your own origin, then gradually expand as needed.',\n code: \"Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data: https:; font-src 'self'\",\n effort: 'moderate',\n docsUrl: 'https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP',\n tags: ['security', 'headers'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const page = ctx.pages?.[0];\n const headers = page?.fetchResult.headers ?? {};\n const csp = headers['content-security-policy'];\n\n if (csp) {\n return this.pass(\n 'Content-Security-Policy header is present.',\n 'Content-Security-Policy header present on homepage response',\n `content-security-policy: ${csp.length > 120 ? csp.slice(0, 120) + '...' : csp}`,\n page?.url,\n );\n }\n\n return this.fail(\n 'Content-Security-Policy header is missing. This header helps prevent XSS and injection attacks.',\n 'Content-Security-Policy header present on homepage response',\n 'Header not found',\n {\n priority: 'high',\n description:\n \"AI trust-scoring systems check for CSP headers as a signal of site security maturity. Sites without CSP are flagged as potentially compromised, which can reduce your content's trust score in AI-generated recommendations. CSP also prevents injected scripts from altering the content AI agents crawl.\",\n code: \"Content-Security-Policy: default-src 'self'; script-src 'self'\",\n },\n page?.url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class ContentTypeOptionsAudit extends Audit {\n static override meta: AuditMeta = {\n id: '8.4',\n category: 'technical-readiness',\n title: 'X-Content-Type-Options: nosniff',\n failureTitle: 'X-Content-Type-Options: nosniff',\n description:\n 'AI agents that fetch your JSON-LD, llms.txt, or API responses need correct MIME types to parse them. Without nosniff, browsers and agents may MIME-sniff responses incorrectly, causing JSON to be treated as HTML or plain text to be treated as a download.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'Without the nosniff directive, browsers and AI agents may MIME-sniff your responses and misinterpret their format. JSON-LD can be treated as HTML, API responses parsed as plain text, and structured data silently ignored — breaking schema extraction and product data ingestion.',\n fix: 'Add the X-Content-Type-Options: nosniff header to all responses. Most web servers and CDNs support this as a single configuration line.',\n code: 'X-Content-Type-Options: nosniff',\n effort: 'trivial',\n docsUrl: 'https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options',\n tags: ['security', 'headers'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const page = ctx.pages?.[0];\n const headers = page?.fetchResult.headers ?? {};\n const value = headers['x-content-type-options'];\n\n if (value && value.toLowerCase().includes('nosniff')) {\n return this.pass(\n 'X-Content-Type-Options is set to nosniff.',\n 'X-Content-Type-Options: nosniff',\n `x-content-type-options: ${value}`,\n page?.url,\n );\n }\n\n if (value) {\n return this.warn(\n `X-Content-Type-Options header is present but not set to nosniff: \"${value}\"`,\n 'X-Content-Type-Options: nosniff',\n `x-content-type-options: ${value}`,\n {\n priority: 'medium',\n description: 'Set the X-Content-Type-Options header value to \"nosniff\".',\n code: 'X-Content-Type-Options: nosniff',\n },\n page?.url,\n );\n }\n\n return this.fail(\n 'X-Content-Type-Options header is missing. This prevents MIME-type sniffing attacks.',\n 'X-Content-Type-Options: nosniff',\n 'Header not found',\n {\n priority: 'medium',\n description:\n 'AI agents that fetch your JSON-LD, llms.txt, or API responses need correct MIME types to parse them. Without nosniff, browsers and agents may MIME-sniff responses incorrectly, causing JSON to be treated as HTML or plain text to be treated as a download.',\n code: 'X-Content-Type-Options: nosniff',\n },\n page?.url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class ReferrerPolicyAudit extends Audit {\n static override meta: AuditMeta = {\n id: '8.5',\n category: 'technical-readiness',\n title: 'Referrer-Policy header',\n failureTitle: 'Referrer-Policy header',\n description:\n 'AI trust-scoring systems check for Referrer-Policy as a privacy maturity signal. Without it, your site leaks full URL paths in referrer headers to third parties, which AI security audits flag as a privacy concern that can reduce trust scores.',\n scoreDisplayMode: 'binary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n \"Without a Referrer-Policy header, your site leaks full URL paths (including query parameters) in HTTP Referer headers when users navigate to external links. AI security audits flag this as a privacy vulnerability, and trust-scoring systems lower your site's rating. Sensitive URL parameters like session tokens or search queries may be exposed to third parties.\",\n fix: 'Add a Referrer-Policy header to your server responses. The recommended value is \"strict-origin-when-cross-origin\", which sends the full URL for same-origin requests but only the origin for cross-origin requests.',\n code: 'Referrer-Policy: strict-origin-when-cross-origin',\n effort: 'trivial',\n docsUrl: 'https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Referrer-Policy',\n tags: ['security', 'headers', 'privacy'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const page = ctx.pages?.[0];\n const headers = page?.fetchResult.headers ?? {};\n const value = headers['referrer-policy'];\n\n if (value) {\n return this.pass(\n `Referrer-Policy header is present: ${value}`,\n 'Referrer-Policy header present on homepage response',\n `referrer-policy: ${value}`,\n page?.url,\n );\n }\n\n return this.fail(\n 'Referrer-Policy header is missing from the homepage response.',\n 'Referrer-Policy header present on homepage response',\n 'Header not found',\n {\n priority: 'medium',\n description:\n 'AI trust-scoring systems check for Referrer-Policy as a privacy maturity signal. Without it, your site leaks full URL paths in referrer headers to third parties, which AI security audits flag as a privacy concern that can reduce trust scores.',\n code: 'Referrer-Policy: strict-origin-when-cross-origin',\n },\n page?.url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class PermissionsPolicyAudit extends Audit {\n static override meta: AuditMeta = {\n id: '8.6',\n category: 'technical-readiness',\n title: 'Permissions-Policy header',\n failureTitle: 'Permissions-Policy header',\n description:\n 'AI browser agents that visit your site may trigger permission prompts for camera, microphone, or geolocation if Permissions-Policy is not set. These prompts block agent workflows and are flagged as security concerns by AI trust-scoring systems.',\n scoreDisplayMode: 'binary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n \"Without a Permissions-Policy header, AI browser agents visiting your site may trigger unexpected permission prompts for camera, microphone, or geolocation. These prompts block automated agent workflows entirely and are flagged by AI trust-scoring systems as a security concern, reducing your site's trust score.\",\n fix: 'Add a Permissions-Policy header that disables sensitive browser features your site does not use. Deny camera, microphone, and geolocation unless your site explicitly requires them.',\n code: 'Permissions-Policy: camera=(), microphone=(), geolocation=(), payment=()',\n effort: 'trivial',\n docsUrl: 'https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Permissions-Policy',\n tags: ['security', 'headers', 'privacy'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const page = ctx.pages?.[0];\n const headers = page?.fetchResult.headers ?? {};\n const value = headers['permissions-policy'];\n\n if (value) {\n return this.pass(\n `Permissions-Policy header is present: ${value.length > 120 ? value.slice(0, 120) + '...' : value}`,\n 'Permissions-Policy header present on homepage response',\n `permissions-policy: ${value.length > 120 ? value.slice(0, 120) + '...' : value}`,\n page?.url,\n );\n }\n\n return this.fail(\n 'Permissions-Policy header is missing from the homepage response.',\n 'Permissions-Policy header present on homepage response',\n 'Header not found',\n {\n priority: 'medium',\n description:\n 'AI browser agents that visit your site may trigger permission prompts for camera, microphone, or geolocation if Permissions-Policy is not set. These prompts block agent workflows and are flagged as security concerns by AI trust-scoring systems.',\n code: 'Permissions-Policy: camera=(), microphone=(), geolocation=()',\n },\n page?.url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class SecurityTxtAudit extends Audit {\n static override meta: AuditMeta = {\n id: '8.7',\n category: 'technical-readiness',\n title: 'security.txt exists',\n failureTitle: 'security.txt exists',\n description:\n 'AI trust-scoring systems check for security.txt as a signal of responsible disclosure practices. Its presence contributes to a higher overall trust score for your site in enterprise AI frameworks that evaluate site maturity before recommending it in answers.',\n scoreDisplayMode: 'binary',\n weight: 1.0,\n defaultPriority: 'low',\n guidance: {\n impact:\n 'AI trust-scoring systems check for /.well-known/security.txt as a signal that your organization follows responsible disclosure practices. Its presence contributes to a higher overall trust score in enterprise AI frameworks that evaluate site maturity, making your content more likely to be recommended in AI-generated answers.',\n fix: 'Create a security.txt file at /.well-known/security.txt with at minimum a Contact field (email or URL), an Expires date, and preferred languages. Optionally include your security policy URL and PGP key.',\n code: 'Contact: mailto:security@yoursite.com\\nExpires: 2027-12-31T23:59:59.000Z\\nPreferred-Languages: en\\nPolicy: https://yoursite.com/security-policy',\n effort: 'trivial',\n docsUrl: 'https://securitytxt.org/',\n tags: ['security', 'trust', 'compliance'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const page = ctx.pages?.[0];\n const file = ctx.rootFiles['/.well-known/security.txt'];\n\n if (file && file.status === 200) {\n return this.pass(\n 'security.txt is present at /.well-known/security.txt.',\n '/.well-known/security.txt returns 200',\n `Status ${file.status}`,\n page?.url,\n );\n }\n\n return this.fail(\n 'security.txt is missing. This file helps security researchers report vulnerabilities responsibly.',\n '/.well-known/security.txt returns 200',\n file ? `Status ${file.status}` : 'File not fetched',\n {\n priority: 'low',\n description:\n 'AI trust-scoring systems check for security.txt as a signal of responsible disclosure practices. Its presence contributes to a higher overall trust score for your site in enterprise AI frameworks that evaluate site maturity before recommending it in answers.',\n code: 'Contact: mailto:security@example.com\\nExpires: 2026-12-31T23:59:59.000Z\\nPreferred-Languages: en',\n docsUrl: 'https://securitytxt.org/',\n },\n page?.url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class CorsAiFilesAudit extends Audit {\n static override meta: AuditMeta = {\n id: '8.8',\n category: 'technical-readiness',\n title: 'CORS on AI files',\n failureTitle: 'CORS on AI files',\n description:\n 'Without CORS headers, AI agents running in browser contexts cannot fetch your llms.txt or API spec. Browser-based AI tools, ChatGPT plugins, and MCP clients are all blocked by same-origin policy, making your AI-facing files completely inaccessible to cross-origin agents.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'Browser-based AI tools, ChatGPT plugins, and MCP clients all run in browser contexts governed by the same-origin policy. Without CORS headers on your llms.txt and AI catalog, these agents receive a network error instead of your content — making your AI-facing files completely invisible to the fastest-growing category of AI consumers.',\n fix: 'Add Access-Control-Allow-Origin and Access-Control-Allow-Methods headers to your /llms.txt and /.well-known/ai-catalog.json responses. Use a wildcard origin (*) unless you need to restrict access to specific domains.',\n code: 'Access-Control-Allow-Origin: *\\nAccess-Control-Allow-Methods: GET, OPTIONS',\n effort: 'easy',\n docsUrl: 'https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS',\n tags: ['cors', 'ai-files', 'headers'],\n },\n };\n\n async audit(ctx: CheckContext): Promise<AuditResult> {\n const page = ctx.pages?.[0];\n const aiPaths = ['/llms.txt', '/.well-known/ai-catalog.json'];\n const corsResults: Array<{ path: string; hasCors: boolean }> = [];\n\n for (const path of aiPaths) {\n try {\n const result = await ctx.fetch({\n url: `${ctx.baseUrl}${path}`,\n method: 'OPTIONS',\n });\n const acaoValue = result.headers['access-control-allow-origin'];\n const hasCors = acaoValue === '*' || (typeof acaoValue === 'string' && acaoValue.length > 0);\n corsResults.push({ path, hasCors });\n } catch {\n corsResults.push({ path, hasCors: false });\n }\n }\n\n const withCors = corsResults.filter((r) => r.hasCors);\n const withoutCors = corsResults.filter((r) => !r.hasCors);\n\n if (withoutCors.length === 0) {\n return this.pass(\n 'All AI files have CORS headers (Access-Control-Allow-Origin).',\n 'OPTIONS requests to /llms.txt and /.well-known/ai-catalog.json return Access-Control-Allow-Origin',\n `CORS enabled: ${withCors.map((r) => r.path).join(', ')}`,\n page?.url,\n );\n }\n\n if (withCors.length > 0) {\n return this.warn(\n `Some AI files are missing CORS headers: ${withoutCors.map((r) => r.path).join(', ')}`,\n 'OPTIONS requests to /llms.txt and /.well-known/ai-catalog.json return Access-Control-Allow-Origin',\n `CORS present: ${withCors.map((r) => r.path).join(', ')}; Missing: ${withoutCors.map((r) => r.path).join(', ')}`,\n {\n priority: 'medium',\n description:\n 'Without CORS headers, AI agents running in browser contexts cannot fetch your llms.txt or AI catalog. Browser-based AI tools and ChatGPT plugins are blocked by same-origin policy, making your AI-facing files inaccessible to the agents that need them most.',\n code: 'Access-Control-Allow-Origin: *\\nAccess-Control-Allow-Methods: GET, OPTIONS',\n },\n page?.url,\n );\n }\n\n return this.fail(\n 'No AI files have CORS headers. Cross-origin AI agents cannot access these files.',\n 'OPTIONS requests to /llms.txt and /.well-known/ai-catalog.json return Access-Control-Allow-Origin',\n `No CORS headers on: ${withoutCors.map((r) => r.path).join(', ')}`,\n {\n priority: 'medium',\n description:\n 'Without CORS headers, AI agents running in browser contexts cannot fetch your llms.txt or API spec. Browser-based AI tools, ChatGPT plugins, and MCP clients are all blocked by same-origin policy, making your AI-facing files completely inaccessible to cross-origin agents.',\n code: 'Access-Control-Allow-Origin: *\\nAccess-Control-Allow-Methods: GET, OPTIONS',\n },\n page?.url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class CorsApiRoutesAudit extends Audit {\n static override meta: AuditMeta = {\n id: '8.9',\n category: 'technical-readiness',\n title: 'CORS on API routes',\n failureTitle: 'CORS on API routes',\n description:\n 'Without CORS headers on your API routes, AI agents running in browser contexts (ChatGPT plugins, MCP clients, browser-based tools) cannot make cross-origin API requests. This blocks all agentic workflows that need to call your API on behalf of users.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'AI agents running in browser contexts (ChatGPT plugins, MCP clients, browser extensions) must pass CORS preflight checks before making API calls. Without CORS headers, every cross-origin API request is silently blocked, preventing all agentic workflows that need to query your product catalog, check inventory, or place orders on behalf of users.',\n fix: 'Configure your API routes to respond to OPTIONS preflight requests with Access-Control-Allow-Origin, Access-Control-Allow-Methods, and Access-Control-Allow-Headers. Apply this to all /api/ routes that AI agents may call.',\n code: 'Access-Control-Allow-Origin: *\\nAccess-Control-Allow-Methods: GET, POST, OPTIONS\\nAccess-Control-Allow-Headers: Content-Type, Authorization',\n effort: 'easy',\n docsUrl: 'https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS',\n tags: ['cors', 'api', 'headers'],\n },\n };\n\n async audit(ctx: CheckContext): Promise<AuditResult> {\n const page = ctx.pages?.[0];\n\n // Check if an OpenAPI spec was found in rootFiles\n const openapiPaths = ['/openapi.json', '/openapi.yaml', '/swagger.json'];\n const hasOpenApi = openapiPaths.some(\n (p) => ctx.rootFiles[p] && ctx.rootFiles[p].status === 200,\n );\n\n if (!hasOpenApi) {\n return this.warn(\n 'No OpenAPI spec found — cannot verify CORS on API routes.',\n 'OPTIONS request to /api/ returns Access-Control-Allow-Origin header',\n 'No OpenAPI specification detected',\n {\n priority: 'low',\n description:\n 'If you have API routes, AI agents cannot call them from browser contexts without CORS headers. Publishing an OpenAPI spec with CORS-enabled endpoints enables agentic workflows where AI tools can query your API on behalf of users.',\n code: 'Access-Control-Allow-Origin: *\\nAccess-Control-Allow-Methods: GET, POST, OPTIONS',\n },\n page?.url,\n );\n }\n\n try {\n // Try both with and without trailing slash since some frameworks redirect\n let result = await ctx.fetch({\n url: `${ctx.baseUrl}/api/`,\n method: 'OPTIONS',\n });\n if (result.status >= 300 && result.status < 400) {\n result = await ctx.fetch({\n url: `${ctx.baseUrl}/api`,\n method: 'OPTIONS',\n });\n }\n const acaoValue = result.headers['access-control-allow-origin'];\n const hasCors = acaoValue === '*' || (typeof acaoValue === 'string' && acaoValue.length > 0);\n\n if (hasCors) {\n return this.pass(\n 'API routes have CORS headers enabled.',\n 'OPTIONS request to /api/ returns Access-Control-Allow-Origin header',\n `access-control-allow-origin: ${result.headers['access-control-allow-origin']}`,\n page?.url,\n );\n }\n\n return this.fail(\n 'API routes are missing CORS headers. AI agents cannot make cross-origin API requests.',\n 'OPTIONS request to /api/ returns Access-Control-Allow-Origin header',\n 'No Access-Control-Allow-Origin header on /api/',\n {\n priority: 'high',\n description:\n 'Without CORS headers on your API routes, AI agents running in browser contexts (ChatGPT plugins, MCP clients, browser-based tools) cannot make cross-origin API requests. This blocks all agentic workflows that need to call your API on behalf of users.',\n code: 'Access-Control-Allow-Origin: *\\nAccess-Control-Allow-Methods: GET, POST, OPTIONS\\nAccess-Control-Allow-Headers: Content-Type, Authorization',\n },\n page?.url,\n );\n } catch {\n return this.warn(\n 'Failed to fetch OPTIONS /api/ — cannot verify CORS.',\n 'OPTIONS request to /api/ returns Access-Control-Allow-Origin header',\n 'Fetch error on OPTIONS /api/',\n {\n priority: 'medium',\n description:\n 'AI agents making cross-origin API calls first send an OPTIONS preflight request. If your /api/ endpoint does not respond to OPTIONS with CORS headers, all subsequent agent requests are blocked by the browser, preventing any agentic API interaction.',\n code: 'Access-Control-Allow-Origin: *\\nAccess-Control-Allow-Methods: GET, POST, OPTIONS',\n },\n page?.url,\n );\n }\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class CorrectContentTypesAudit extends Audit {\n static override meta: AuditMeta = {\n id: '8.10',\n category: 'technical-readiness',\n title: 'Correct Content-Types',\n failureTitle: 'Correct Content-Types',\n description:\n 'AI agents use Content-Type headers to determine how to parse your files. Incorrect MIME types cause JSON files to be treated as plain text (breaking schema parsing) or XML to be treated as HTML (breaking sitemap crawling). Fix Content-Type headers to match each file format.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'Incorrect Content-Type headers cause AI agents to misparse your files. JSON served as text/html breaks structured data extraction, XML sitemaps served as text/plain prevent crawl discovery, and llms.txt served as application/octet-stream triggers downloads instead of being read. This silently breaks the AI data pipeline.',\n fix: 'Configure your web server or CDN to serve each file with the correct MIME type: application/json for JSON files, application/xml for XML sitemaps, and text/plain for llms.txt.',\n code: 'llms.txt: Content-Type: text/plain\\nopenapi.json: Content-Type: application/json\\nai-catalog.json: Content-Type: application/json\\nsitemap.xml: Content-Type: application/xml',\n effort: 'easy',\n docsUrl: 'https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Type',\n tags: ['headers', 'ai-files', 'configuration'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const page = ctx.pages?.[0];\n\n const expectations: Array<{\n path: string;\n expectedTypes: string[];\n label: string;\n }> = [\n { path: '/llms.txt', expectedTypes: ['text/plain', 'text/markdown'], label: 'llms.txt' },\n {\n path: '/.well-known/ai-catalog.json',\n expectedTypes: ['application/json', 'text/json'],\n label: 'ai-catalog.json',\n },\n {\n path: '/openapi.json',\n expectedTypes: ['application/json', 'text/json', 'application/yaml', 'text/yaml'],\n label: 'openapi.json',\n },\n {\n path: '/sitemap.xml',\n expectedTypes: ['application/xml', 'text/xml'],\n label: 'sitemap.xml',\n },\n ];\n\n const correct: string[] = [];\n const incorrect: Array<{ label: string; expected: string; actual: string }> = [];\n let checked = 0;\n\n for (const { path, expectedTypes, label } of expectations) {\n const file = ctx.rootFiles[path];\n if (!file || file.status !== 200) continue;\n checked++;\n\n const ct = file.contentType.toLowerCase().split(';')[0].trim();\n if (expectedTypes.some((et) => ct.includes(et))) {\n correct.push(label);\n } else {\n incorrect.push({ label, expected: expectedTypes[0]!, actual: ct });\n }\n }\n\n if (checked === 0) {\n return this.warn(\n 'No AI/data files found to verify Content-Type headers.',\n 'JSON files served as application/json, XML as application/xml, llms.txt as text/plain',\n 'No applicable files found',\n undefined,\n page?.url,\n );\n }\n\n if (incorrect.length === 0) {\n return this.pass(\n `All checked files have correct Content-Type headers: ${correct.join(', ')}`,\n 'JSON files served as application/json, XML as application/xml, llms.txt as text/plain',\n `Correct: ${correct.join(', ')}`,\n page?.url,\n );\n }\n\n const details = incorrect\n .map((i) => `${i.label}: expected ${i.expected}, got ${i.actual}`)\n .join('; ');\n\n return this.fail(\n `Incorrect Content-Type on some files: ${details}`,\n 'JSON files served as application/json, XML as application/xml, llms.txt as text/plain',\n `Incorrect: ${details}`,\n {\n priority: 'medium',\n description:\n 'AI agents use Content-Type headers to determine how to parse your files. Incorrect MIME types cause JSON files to be treated as plain text (breaking schema parsing) or XML to be treated as HTML (breaking sitemap crawling). Fix Content-Type headers to match each file format.',\n code: incorrect.map((i) => `${i.label}: Content-Type: ${i.expected}`).join('\\n'),\n },\n page?.url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class CacheHeadersAudit extends Audit {\n static override meta: AuditMeta = {\n id: '8.11',\n category: 'technical-readiness',\n title: 'Cache headers on AI files',\n failureTitle: 'Cache headers on AI files',\n description:\n 'Add Cache-Control headers to AI-facing files to improve performance and reduce unnecessary requests.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'low',\n guidance: {\n impact:\n 'Without Cache-Control headers on AI-facing files, every AI agent request re-fetches the full file from your server. This wastes bandwidth, increases server load, and slows down agent crawling — especially during traffic spikes when multiple agents poll simultaneously.',\n fix: 'Add a Cache-Control response header to your /llms.txt and /openapi.json routes. A value of \"public, max-age=3600\" lets agents cache the file for one hour, which is a good balance between freshness and efficiency.',\n code: 'Cache-Control: public, max-age=3600',\n effort: 'trivial',\n tags: ['performance', 'caching', 'ai-files'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const page = ctx.pages?.[0];\n const aiPaths = ['/llms.txt', '/openapi.json'];\n const withCache: string[] = [];\n const withoutCache: string[] = [];\n let checked = 0;\n\n for (const path of aiPaths) {\n const file = ctx.rootFiles[path];\n if (!file || file.status !== 200) continue;\n checked++;\n\n if (file.headers['cache-control']) {\n withCache.push(path);\n } else {\n withoutCache.push(path);\n }\n }\n\n if (checked === 0) {\n return this.warn(\n 'No AI files (/llms.txt, /openapi.json) found to check cache headers.',\n 'AI files have a Cache-Control header',\n 'No applicable files found',\n undefined,\n page?.url,\n );\n }\n\n if (withoutCache.length === 0) {\n return this.pass(\n `All AI files have Cache-Control headers: ${withCache.join(', ')}`,\n 'AI files have a Cache-Control header',\n `Cache-Control present on: ${withCache.join(', ')}`,\n page?.url,\n );\n }\n\n if (withCache.length > 0) {\n return this.warn(\n `Some AI files are missing Cache-Control headers: ${withoutCache.join(', ')}`,\n 'AI files have a Cache-Control header',\n `Present: ${withCache.join(', ')}; Missing: ${withoutCache.join(', ')}`,\n {\n priority: 'low',\n description:\n 'Add Cache-Control headers to AI files to reduce server load from repeated agent requests.',\n code: 'Cache-Control: public, max-age=3600',\n },\n page?.url,\n );\n }\n\n return this.fail(\n 'No AI files have Cache-Control headers. Agents may re-fetch these files unnecessarily.',\n 'AI files have a Cache-Control header',\n `Missing Cache-Control: ${withoutCache.join(', ')}`,\n {\n priority: 'low',\n description:\n 'Add Cache-Control headers to AI-facing files to improve performance and reduce unnecessary requests.',\n code: 'Cache-Control: public, max-age=3600',\n },\n page?.url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class FastResponseTimeAudit extends Audit {\n static override meta: AuditMeta = {\n id: '8.12',\n category: 'technical-readiness',\n title: 'Fast response time',\n failureTitle: 'Fast response time',\n description:\n 'AI crawlers have strict timeout budgets per page. GPTBot and ClaudeBot typically abandon requests over 2-3 seconds, and slow TTFB reduces the number of pages they crawl per session. Optimize to under 800ms with server-side caching, CDN, and reduced backend processing.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'high',\n guidance: {\n impact:\n 'AI crawlers like GPTBot and ClaudeBot enforce strict per-page timeout budgets (typically 2-3 seconds). A slow TTFB means fewer of your pages get crawled per session, and pages that exceed the timeout are abandoned entirely. Over time, this results in incomplete coverage in AI knowledge bases — your products and content simply do not appear in AI-generated answers.',\n fix: 'Reduce Time to First Byte (TTFB) to under 800ms. Use server-side caching (Redis, in-memory), deploy behind a CDN with edge caching, minimize database queries on critical paths, and consider pre-rendering or static generation for content pages.',\n code: '# Nginx microcaching example:\\nproxy_cache_path /tmp/cache levels=1:2 keys_zone=ai:10m max_size=1g;\\nproxy_cache_valid 200 1m;\\nadd_header X-Cache-Status $upstream_cache_status;',\n effort: 'moderate',\n docsUrl: 'https://web.dev/articles/ttfb',\n tags: ['performance', 'speed'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const page = ctx.pages?.[0];\n\n if (!page) {\n return this.warn(\n 'No homepage data available to measure response time.',\n 'Homepage TTFB < 800ms',\n 'No homepage fetched',\n undefined,\n undefined,\n );\n }\n\n const ttfb = page.fetchResult.ttfbMs;\n\n // If the request failed (error or status 0), TTFB of 0 is not a real measurement\n if (page.fetchResult.error || page.fetchResult.status === 0) {\n return this.fail(\n 'Could not measure response time — request failed.',\n 'Homepage TTFB < 800ms',\n page.fetchResult.error\n ? `Error: ${page.fetchResult.error}`\n : 'Request failed with status 0',\n {\n priority: 'critical',\n description:\n 'The homepage request failed entirely, so response time could not be measured. AI crawlers that cannot reach your site will exclude it from their knowledge bases. Verify the server is responding correctly.',\n code: '# Check server health:\\ncurl -I https://your-site.com/',\n },\n page.url,\n );\n }\n\n if (ttfb < 800) {\n return this.pass(\n `Homepage TTFB is ${ttfb}ms — well within the 800ms threshold.`,\n 'Homepage TTFB < 800ms',\n `TTFB: ${ttfb}ms`,\n page.url,\n );\n }\n\n return this.fail(\n `Homepage TTFB is ${ttfb}ms — exceeds the 800ms threshold. Slow responses degrade AI agent experience.`,\n 'Homepage TTFB < 800ms',\n `TTFB: ${ttfb}ms`,\n {\n priority: 'high',\n description:\n 'AI crawlers have strict timeout budgets per page. GPTBot and ClaudeBot typically abandon requests over 2-3 seconds, and slow TTFB reduces the number of pages they crawl per session. Optimize to under 800ms with server-side caching, CDN, and reduced backend processing.',\n code: '# For nginx, add microcaching:\\nproxy_cache_valid 200 1m;\\nadd_header X-Cache-Status $upstream_cache_status;',\n },\n page.url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\nimport { getWordCount, getMainContentText } from '../../parser';\n\nexport class ServerRenderedAudit extends Audit {\n static override meta: AuditMeta = {\n id: '8.13',\n category: 'technical-readiness',\n title: 'Server-rendered content',\n failureTitle: 'Server-rendered content',\n description:\n 'AI crawlers like GPTBot and ClaudeBot do not execute JavaScript. Content only visible after JS execution is completely invisible to them, meaning your site effectively has no content in AI knowledge bases. Use SSR (server-side rendering) or SSG (static site generation) to serve content in the initial HTML response.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'critical',\n guidance: {\n impact:\n 'AI crawlers (GPTBot, ClaudeBot, PerplexityBot) do not execute JavaScript. If your content is only rendered client-side, these crawlers see an empty or near-empty page. Your products, articles, and brand information are completely absent from AI knowledge bases, meaning AI-generated answers never reference your site.',\n fix: 'Switch from client-side rendering to server-side rendering (SSR) or static site generation (SSG). Frameworks like Next.js, Nuxt, SvelteKit, and Astro all support SSR/SSG. Ensure your homepage and key landing pages return meaningful HTML content in the initial response.',\n code: '// Next.js App Router (server component by default):\\nexport default async function Page() {\\n const data = await fetchProducts();\\n return <ProductList items={data} />;\\n}\\n\\n// Or with getServerSideProps (Pages Router):\\nexport async function getServerSideProps() {\\n const data = await fetchProducts();\\n return { props: { data } };\\n}',\n effort: 'complex',\n docsUrl: 'https://web.dev/articles/rendering-on-the-web',\n tags: ['rendering', 'ssr', 'critical'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const page = ctx.pages?.[0];\n\n if (!page) {\n return this.warn(\n 'No homepage data available to check server-rendered content.',\n 'Homepage <main> has > 50 words or > 200 characters of text content',\n 'No homepage fetched',\n undefined,\n undefined,\n );\n }\n\n const $ = page.$;\n const wordCount = getWordCount($);\n const mainText = getMainContentText($);\n\n if (wordCount > 50 || mainText.length > 200) {\n return this.pass(\n `Homepage has meaningful server-rendered content (${wordCount} words, ${mainText.length} characters).`,\n 'Homepage <main> has > 50 words or > 200 characters of text content',\n `${wordCount} words, ${mainText.length} characters`,\n page.url,\n );\n }\n\n return this.fail(\n `Homepage has minimal server-rendered content (${wordCount} words, ${mainText.length} characters). AI agents cannot read client-side-only rendered content.`,\n 'Homepage <main> has > 50 words or > 200 characters of text content',\n `${wordCount} words, ${mainText.length} characters`,\n {\n priority: 'critical',\n description:\n 'AI crawlers like GPTBot and ClaudeBot do not execute JavaScript. Content only visible after JS execution is completely invisible to them, meaning your site effectively has no content in AI knowledge bases. Use SSR (server-side rendering) or SSG (static site generation) to serve content in the initial HTML response.',\n code: '// Next.js SSR example:\\nexport async function getServerSideProps() {\\n const data = await fetchData();\\n return { props: { data } };\\n}',\n },\n page.url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\nimport { extractScripts } from '../../parser';\n\nexport class NoRenderBlockingAudit extends Audit {\n static override meta: AuditMeta = {\n id: '8.14',\n category: 'technical-readiness',\n title: 'No render-blocking resources',\n failureTitle: 'No render-blocking resources',\n description:\n 'Render-blocking scripts delay the HTML content that AI crawlers extract. Since AI agents do not execute JavaScript, blocking scripts add latency without providing any benefit to AI crawling. Use defer, async, or type=\"module\" to unblock HTML delivery.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'Synchronous scripts in <head> block HTML parsing and delay content delivery. Since AI crawlers do not execute JavaScript, these scripts add pure latency with zero benefit — the crawler waits for scripts to download but never runs them. This wastes crawl budget and slows TTFB, reducing the number of pages AI agents can index.',\n fix: 'Add the defer or async attribute to all <script> tags in <head>, or convert them to type=\"module\". Move non-critical scripts to the end of <body> if they cannot be deferred.',\n code: '<!-- Before (blocking): -->\\n<script src=\"app.js\"></script>\\n\\n<!-- After (non-blocking): -->\\n<script src=\"app.js\" defer></script>',\n effort: 'easy',\n docsUrl: 'https://web.dev/articles/render-blocking-resources',\n tags: ['performance', 'rendering', 'scripts'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const page = ctx.pages?.[0];\n\n if (!page) {\n return this.warn(\n 'No homepage data available to check for render-blocking resources.',\n 'No synchronous <script> tags in <head> without defer/async/type=module',\n 'No homepage fetched',\n undefined,\n undefined,\n );\n }\n\n const $ = page.$;\n const allScripts = extractScripts($);\n\n // Build a set of src values for scripts in <head> so we can identify head scripts\n const headScriptSrcs = new Set<string>();\n $('head script[src]').each((_, el) => {\n const src = $(el).attr('src');\n if (src) headScriptSrcs.add(src);\n });\n\n // Count inline scripts in <head> (no src)\n const headInlineCount = $('head script:not([src])').length;\n\n // Filter for blocking scripts: external scripts in <head> without async/defer/module\n // Scripts with noModule are ignored by modern browsers, so they are not render-blocking\n const blockingScripts = allScripts.filter(\n (s) =>\n !s.inline &&\n s.src &&\n headScriptSrcs.has(s.src) &&\n !s.async &&\n !s.defer &&\n !s.isModule &&\n !s.noModule,\n );\n\n const totalHeadScripts = headScriptSrcs.size + headInlineCount;\n\n if (blockingScripts.length === 0) {\n // Check if the page body appears to be empty or very short\n /* v8 ignore next */\n const bodyText = page.fetchResult.body ?? '';\n if (bodyText.length < 100) {\n return this.warn(\n 'Page appears to have no content — may not be rendering correctly.',\n 'No synchronous <script> tags in <head> without defer/async/type=module',\n `Page body is only ${bodyText.length} characters`,\n {\n priority: 'high',\n description:\n 'The page has virtually no HTML content, which may indicate a rendering failure or a client-side-only application. AI crawlers cannot process JavaScript, so an empty initial HTML response means no content will be indexed.',\n code: '<!-- Ensure your server returns meaningful HTML content in the initial response -->',\n },\n page.url,\n );\n }\n\n return this.pass(\n 'No render-blocking synchronous scripts found in <head>.',\n 'No synchronous <script> tags in <head> without defer/async/type=module',\n `${totalHeadScripts} script(s) in <head>, none blocking`,\n page.url,\n );\n }\n\n /* v8 ignore next */\n const blockingSrcs = blockingScripts\n .map((s) => s.src ?? 'unknown')\n .slice(0, 5)\n .join(', ');\n\n return this.fail(\n `Found ${blockingScripts.length} render-blocking script(s) in <head>. These delay page rendering for AI agents.`,\n 'No synchronous <script> tags in <head> without defer/async/type=module',\n `${blockingScripts.length} blocking script(s): ${blockingSrcs}`,\n {\n priority: 'medium',\n description:\n 'Render-blocking scripts delay the HTML content that AI crawlers extract. Since AI agents do not execute JavaScript, blocking scripts add latency without providing any benefit to AI crawling. Use defer, async, or type=\"module\" to unblock HTML delivery.',\n code: '<script src=\"app.js\" defer></script>',\n },\n page.url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\nimport { extractImages } from '../../parser';\n\nexport class ImageDimensionsAudit extends Audit {\n static override meta: AuditMeta = {\n id: '8.15',\n category: 'technical-readiness',\n title: 'Images have explicit dimensions',\n failureTitle: 'Images have explicit dimensions',\n description:\n 'AI agents that use visual screenshots (like Claude computer use) need stable page layouts to identify interactive elements. Missing image dimensions cause layout shifts that move elements between screenshots, breaking coordinate-based click targeting in agentic workflows.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'Missing width and height attributes on images cause layout shifts (CLS) as images load. AI agents that use visual screenshots (such as Claude computer use) see elements jump positions between frames, breaking coordinate-based click targeting. High CLS also hurts Core Web Vitals scores, which AI trust-scoring systems factor into content quality rankings.',\n fix: 'Add explicit width and height attributes to all <img> tags. Use CSS aspect-ratio or the HTML attributes to reserve space before the image loads. For responsive images, set width/height to the intrinsic dimensions and use CSS to scale.',\n code: '<img src=\"product.jpg\" width=\"800\" height=\"600\" alt=\"Product photo\"\\n style=\"max-width: 100%; height: auto;\">',\n effort: 'easy',\n docsUrl: 'https://web.dev/articles/optimize-cls',\n tags: ['performance', 'layout', 'images'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const page = ctx.pages?.[0];\n\n if (!page) {\n return this.warn(\n 'No homepage data available to check image dimensions.',\n 'All <img> tags have width and height attributes',\n 'No homepage fetched',\n undefined,\n undefined,\n );\n }\n\n const rawImages = extractImages(page.$);\n\n if (rawImages.length === 0) {\n return this.pass(\n 'No images found on the homepage.',\n 'All <img> tags have width and height attributes',\n 'No <img> tags found',\n page.url,\n );\n }\n\n // Exclude inline data URI spacers and dummy anchors which do not cause network-delayed CLS\n const images = rawImages.filter((img) => {\n const src = img.src?.trim();\n return src !== '#' && !src?.startsWith('data:image/');\n });\n\n if (images.length === 0) {\n return this.pass(\n 'No external image resources found on the page.',\n 'All <img> tags have width and height attributes',\n 'No external images (only data URIs)',\n page.url,\n );\n }\n\n const withoutDimensions = images.filter((img) => !img.width || !img.height);\n\n if (withoutDimensions.length === 0) {\n return this.pass(\n `All ${images.length} image(s) have explicit width and height attributes.`,\n 'All <img> tags have width and height attributes',\n `${images.length} image(s), all with dimensions`,\n page.url,\n );\n }\n\n const ratio = (images.length - withoutDimensions.length) / images.length;\n const missingSrcs = withoutDimensions\n .map((img) => img.src || '(inline)')\n .slice(0, 5)\n .join(', ');\n\n if (ratio >= 0.5) {\n return this.warn(\n `${withoutDimensions.length} of ${images.length} image(s) are missing explicit width/height attributes. This causes layout shifts.`,\n 'All <img> tags have width and height attributes',\n `Missing dimensions: ${missingSrcs}`,\n {\n priority: 'medium',\n description:\n 'AI agents that use visual screenshots (like Claude computer use) need stable page layouts to identify interactive elements. Missing image dimensions cause layout shifts that move elements between screenshots, breaking coordinate-based click targeting in agentic workflows.',\n code: '<img src=\"photo.jpg\" width=\"800\" height=\"600\" alt=\"...\">',\n },\n page.url,\n );\n }\n\n return this.fail(\n `${withoutDimensions.length} of ${images.length} image(s) are missing explicit width/height attributes. This causes layout shifts.`,\n 'All <img> tags have width and height attributes',\n `Missing dimensions: ${missingSrcs}`,\n {\n priority: 'medium',\n description:\n 'AI agents that use visual screenshots (like Claude computer use) need stable page layouts to identify interactive elements. Missing image dimensions cause layout shifts that move elements between screenshots, breaking coordinate-based click targeting in agentic workflows.',\n code: '<img src=\"photo.jpg\" width=\"800\" height=\"600\" alt=\"...\">',\n },\n page.url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\nimport { extractImages } from '../../parser';\n\nexport class LcpNotLazyAudit extends Audit {\n static override meta: AuditMeta = {\n id: '8.16',\n category: 'technical-readiness',\n title: 'LCP element not lazy-loaded',\n failureTitle: 'LCP element not lazy-loaded',\n description:\n 'AI agents that use visual screenshots see a blank placeholder for lazy-loaded hero images, missing critical visual context. For Core Web Vitals, lazy-loading the LCP element also degrades your performance score, which AI trust-scoring systems factor into content quality rankings.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'high',\n guidance: {\n impact:\n \"Lazy-loading the Largest Contentful Paint (LCP) element delays the most important visual content on the page. AI agents using visual screenshots see a blank placeholder instead of your hero image, and Core Web Vitals scores suffer — both of which reduce your content's ranking in AI trust-scoring systems.\",\n fix: 'Remove loading=\"lazy\" from the first/largest image on the page (the LCP candidate). Instead, add fetchpriority=\"high\" to tell the browser to prioritize loading this image immediately.',\n code: '<!-- Before (bad): -->\\n<img src=\"hero.jpg\" loading=\"lazy\" alt=\"...\">\\n\\n<!-- After (good): -->\\n<img src=\"hero.jpg\" fetchpriority=\"high\" alt=\"...\">',\n effort: 'trivial',\n docsUrl: 'https://web.dev/articles/lcp-lazy-loading',\n tags: ['performance', 'images', 'lcp'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const page = ctx.pages?.[0];\n\n if (!page) {\n return this.warn(\n 'No homepage data available to check LCP element.',\n 'First/largest image does not have loading=\"lazy\"',\n 'No homepage fetched',\n undefined,\n undefined,\n );\n }\n\n const images = extractImages(page.$);\n\n if (images.length === 0) {\n return this.pass(\n 'No images found on the homepage — LCP check not applicable.',\n 'First/largest image does not have loading=\"lazy\"',\n 'No <img> tags found',\n page.url,\n );\n }\n\n // The first image is a reasonable proxy for the LCP element\n const firstImage = images[0];\n\n if (firstImage.loading === 'lazy') {\n return this.fail(\n `The first image (likely LCP element) has loading=\"lazy\", which delays rendering of the most important content.`,\n 'First/largest image does not have loading=\"lazy\"',\n `First image (${firstImage.src || '(inline)'}) has loading=\"lazy\"`,\n {\n priority: 'high',\n description:\n 'AI agents that use visual screenshots see a blank placeholder for lazy-loaded hero images, missing critical visual context. For Core Web Vitals, lazy-loading the LCP element also degrades your performance score, which AI trust-scoring systems factor into content quality rankings.',\n code: '<img src=\"hero.jpg\" fetchpriority=\"high\" alt=\"...\">',\n },\n page.url,\n );\n }\n\n return this.pass(\n 'The first image (likely LCP element) is not lazy-loaded.',\n 'First/largest image does not have loading=\"lazy\"',\n `First image (${firstImage.src || '(inline)'}) — loading=\"${firstImage.loading ?? 'eager (default)'}\"`,\n page.url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class PreconnectHintsAudit extends Audit {\n static override meta: AuditMeta = {\n id: '8.17',\n category: 'technical-readiness',\n title: 'Preconnect hints',\n failureTitle: 'Preconnect hints',\n description:\n 'Preconnect hints reduce the time AI crawlers spend establishing connections to third-party resources. Faster page loads mean AI agents can crawl more of your pages within their time budget, improving overall content coverage in AI knowledge bases.',\n scoreDisplayMode: 'binary',\n weight: 1.0,\n defaultPriority: 'low',\n guidance: {\n impact:\n 'Without preconnect hints, each third-party resource requires a full DNS lookup, TCP handshake, and TLS negotiation before loading can begin. This adds hundreds of milliseconds per origin, slowing overall page load and reducing the number of pages AI crawlers can process within their time budget.',\n fix: 'Add <link rel=\"preconnect\"> tags in <head> for your most critical third-party origins (CDNs, font providers, analytics). Limit to 2-4 origins to avoid diminishing returns.',\n code: '<link rel=\"preconnect\" href=\"https://fonts.googleapis.com\">\\n<link rel=\"preconnect\" href=\"https://cdn.yoursite.com\" crossorigin>',\n effort: 'trivial',\n docsUrl: 'https://web.dev/articles/uses-rel-preconnect',\n tags: ['performance', 'speed', 'resource-hints'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const page = ctx.pages?.[0];\n\n if (!page) {\n return this.warn(\n 'No homepage data available to check preconnect hints.',\n 'At least one <link rel=\"preconnect\"> tag present',\n 'No homepage fetched',\n undefined,\n undefined,\n );\n }\n\n const $ = page.$;\n const preconnects = $('link[rel=\"preconnect\"]');\n\n if (preconnects.length > 0) {\n const hrefs: string[] = [];\n preconnects.each((_, el) => {\n const href = $(el).attr('href');\n if (href) hrefs.push(href);\n });\n\n return this.pass(\n `Found ${preconnects.length} preconnect hint(s): ${hrefs.slice(0, 5).join(', ')}`,\n 'At least one <link rel=\"preconnect\"> tag present',\n `${preconnects.length} preconnect hint(s)`,\n page.url,\n );\n }\n\n return this.fail(\n 'No <link rel=\"preconnect\"> hints found. Preconnect hints speed up connections to critical third-party origins.',\n 'At least one <link rel=\"preconnect\"> tag present',\n 'No preconnect hints found',\n {\n priority: 'low',\n description:\n 'Preconnect hints reduce the time AI crawlers spend establishing connections to third-party resources. Faster page loads mean AI agents can crawl more of your pages within their time budget, improving overall content coverage in AI knowledge bases.',\n code: '<link rel=\"preconnect\" href=\"https://fonts.googleapis.com\">\\n<link rel=\"preconnect\" href=\"https://cdn.yoursite.com\">',\n },\n page.url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\nimport { isSafeUrl } from '../../fetcher';\nimport { extractMarkdownLinks } from '../../parser';\n\nexport class NoBrokenAiEndpointsAudit extends Audit {\n static override meta: AuditMeta = {\n id: '8.18',\n category: 'technical-readiness',\n title: 'No broken AI endpoints',\n failureTitle: 'No broken AI endpoints',\n description:\n \"AI agents follow URLs in your ai-catalog.json, llms.txt, and navigation.json to build a map of your site's AI-consumable resources. Broken links cause agents to lose trust in your manifest files entirely, potentially ignoring all listed endpoints. Fix or remove broken URLs.\",\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'high',\n guidance: {\n impact:\n 'Broken URLs in your AI manifest files (ai-catalog.json, llms.txt, navigation.json) cause agents to lose trust in your entire manifest. After encountering broken links, AI systems may stop following any of your listed endpoints, effectively making all your AI-facing resources undiscoverable.',\n fix: 'Audit all URLs referenced in your ai-catalog.json, llms.txt, and navigation.json files. Fix or remove any that return 404, 500, or connection errors. Set up monitoring to catch broken endpoints before AI agents do.',\n code: '# Verify your AI endpoint URLs:\\ncurl -sI https://yoursite.com/llms.txt | head -1\\ncurl -sI https://yoursite.com/.well-known/ai-catalog.json | head -1\\ncurl -sI https://yoursite.com/openapi.json | head -1',\n effort: 'easy',\n tags: ['ai-files', 'reliability', 'endpoints'],\n },\n };\n\n async audit(ctx: CheckContext): Promise<AuditResult> {\n const page = ctx.pages?.[0];\n\n // Collect URLs from ai-catalog.json, llms.txt, and navigation.json\n const urlsToCheck = new Set<string>();\n\n // From ai-catalog.json\n const aiCatalog = ctx.rootFiles['/.well-known/ai-catalog.json'];\n if (aiCatalog && aiCatalog.status === 200 && aiCatalog.body) {\n try {\n const catalog = JSON.parse(aiCatalog.body);\n if (catalog.services && Array.isArray(catalog.services)) {\n for (const service of catalog.services) {\n if (service.url) {\n urlsToCheck.add(\n service.url.startsWith('http') ? service.url : `${ctx.baseUrl}${service.url}`,\n );\n }\n }\n }\n } catch {\n // Invalid JSON — skip\n }\n }\n\n // From llms.txt — extract URLs.\n // Use the shared Markdown-link parser for list/inline links, then add any\n // remaining loose bare URLs. The old `/https?:\\/\\/[^\\s)>]+/g` regex swept up\n // trailing backticks, brackets, and periods (`https://…SKILL.md\\``), which\n // fabricated phantom \"broken\" endpoints. Strip trailing punctuation so each\n // URL is validated as written; the Set de-dupes by normalized URL.\n const llmsTxt = ctx.rootFiles['/llms.txt'];\n if (llmsTxt && llmsTxt.status === 200 && llmsTxt.body) {\n for (const link of extractMarkdownLinks(llmsTxt.body)) {\n urlsToCheck.add(link.url);\n }\n const matches = llmsTxt.body.match(/https?:\\/\\/[^\\s)\\]>`\"']+/g);\n if (matches) {\n for (const raw of matches) {\n const url = raw.replace(/[.,;:!?'\")\\]`>]+$/, '');\n // v8 ignore next — regex `+` guarantees raw is non-empty; stripping\n // trailing punctuation from `http://…` always leaves ≥7 chars\n /* v8 ignore next */\n if (url) urlsToCheck.add(url);\n }\n }\n }\n\n // From navigation.json\n const navJson = ctx.rootFiles['/navigation.json'];\n if (navJson && navJson.status === 200 && navJson.body) {\n try {\n const nav = JSON.parse(navJson.body);\n const extractUrls = (obj: unknown): void => {\n if (Array.isArray(obj)) {\n for (const item of obj) extractUrls(item);\n } else if (obj && typeof obj === 'object') {\n for (const [key, value] of Object.entries(obj as Record<string, unknown>)) {\n if ((key === 'url' || key === 'href') && typeof value === 'string') {\n urlsToCheck.add(value.startsWith('http') ? value : `${ctx.baseUrl}${value}`);\n } else {\n extractUrls(value);\n }\n }\n }\n };\n extractUrls(nav);\n } catch {\n // Invalid JSON — skip\n }\n }\n\n if (urlsToCheck.size === 0) {\n return this.warn(\n 'No AI endpoint URLs found in ai-catalog.json, llms.txt, or navigation.json to validate.',\n 'All URLs from AI-related files return 200',\n 'No URLs to validate',\n undefined,\n page?.url,\n );\n }\n\n const broken: Array<{ url: string; status: number }> = [];\n const valid: string[] = [];\n\n // Filter out unsafe URLs (SSRF protection) and limit count\n const allUrls = Array.from(urlsToCheck).slice(0, 20);\n const urls: string[] = [];\n for (const url of allUrls) {\n if (await isSafeUrl(url)) urls.push(url);\n }\n\n const results = await Promise.all(\n urls.map(async (url) => {\n try {\n let result = await ctx.fetch({ url, method: 'HEAD' });\n if (result.status >= 400) {\n result = await ctx.fetch({ url, method: 'GET' });\n }\n if (result.status >= 400 && (url.includes('/mcp') || url.includes('/api/'))) {\n const postResult = await ctx.fetch({\n url,\n method: 'POST',\n body: JSON.stringify({\n jsonrpc: '2.0',\n id: 1,\n method: 'initialize',\n params: {\n protocolVersion: '2024-11-05',\n capabilities: {},\n clientInfo: { name: 'agent-lighthouse', version: '1.0.0' },\n },\n }),\n contentType: 'application/json',\n });\n if (postResult.status >= 200 && postResult.status < 400) {\n result = postResult;\n }\n }\n return { url, status: result.status };\n } catch {\n return { url, status: 0 };\n }\n }),\n );\n\n for (const result of results) {\n if (result.status >= 200 && result.status < 400) {\n valid.push(result.url);\n } else {\n broken.push(result);\n }\n }\n\n if (broken.length === 0) {\n return this.pass(\n `All ${valid.length} AI endpoint URL(s) are reachable.`,\n 'All URLs from AI-related files return 200',\n `${valid.length} URL(s) checked, all reachable`,\n page?.url,\n );\n }\n\n const brokenDetails = broken\n .slice(0, 5)\n .map((b) => `${b.url} (${b.status || 'error'})`)\n .join('; ');\n\n if (broken.length === urls.length) {\n return this.fail(\n `${broken.length} of ${urls.length} AI endpoint URL(s) are broken or unreachable: ${brokenDetails}`,\n 'All URLs from AI-related files return 200',\n `Broken: ${broken.length}; Valid: ${valid.length}`,\n {\n priority: 'high',\n description:\n \"AI agents follow URLs in your ai-catalog.json, llms.txt, and navigation.json to build a map of your site's AI-consumable resources. Broken links cause agents to lose trust in your manifest files entirely, potentially ignoring all listed endpoints. Fix or remove broken URLs.\",\n code: '# Verify all URLs in your AI files:\\ncurl -I https://yoursite.com/llms.txt\\ncurl -I https://yoursite.com/.well-known/ai-catalog.json',\n },\n page?.url,\n );\n }\n\n return this.warn(\n `${broken.length} of ${urls.length} AI endpoint URL(s) are broken or unreachable: ${brokenDetails}`,\n 'All URLs from AI-related files return 200',\n `Broken: ${broken.length}; Valid: ${valid.length}`,\n {\n priority: 'high',\n description:\n \"AI agents follow URLs in your ai-catalog.json, llms.txt, and navigation.json to build a map of your site's AI-consumable resources. Broken links cause agents to lose trust in your manifest files entirely, potentially ignoring all listed endpoints. Fix or remove broken URLs.\",\n code: '# Verify all URLs in your AI files:\\ncurl -I https://yoursite.com/llms.txt\\ncurl -I https://yoursite.com/.well-known/ai-catalog.json',\n },\n page?.url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\n// Match a privacy-policy link by anchor text or href. Deliberately specific so\n// product links like \"privacy levers and knobs\" don't false-positive.\nconst PRIVACY_TEXT = /\\bprivacy\\s*(policy|notice|statement|center|&\\s*security|and\\s*security)\\b/;\nconst PRIVACY_HREF =\n /privacy[-_]?(policy|notice|statement|security|center)|\\/privacy(\\.[a-z0-9]+)?($|[/?#])/;\n\n/** Find a linked privacy policy anywhere in the scanned pages' anchors. */\nfunction findPrivacyLink(ctx: CheckContext): string | null {\n for (const page of ctx.pages) {\n let hit: string | null = null;\n page.$('a[href]').each((_, el) => {\n if (hit) return;\n /* v8 ignore next */\n const href = (page.$(el).attr('href') ?? '').trim();\n if (!href) return;\n const text = page.$(el).text().trim().toLowerCase();\n if (text === 'privacy' || PRIVACY_TEXT.test(text) || PRIVACY_HREF.test(href.toLowerCase())) {\n hit = href;\n }\n });\n if (hit) return hit;\n }\n return null;\n}\n\nexport class PrivacyPolicyAudit extends Audit {\n static override meta: AuditMeta = {\n id: '8.19',\n category: 'technical-readiness',\n title: 'Privacy policy exists',\n failureTitle: 'Privacy policy exists',\n description:\n 'Enterprise AI frameworks check for privacy policies before recommending sites in regulated industries. A missing privacy policy reduces your trust score in AI systems that prioritize sites with transparent data handling practices, especially for health, finance, and legal content.',\n scoreDisplayMode: 'binary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'Enterprise AI frameworks and compliance-aware recommendation systems check for a privacy policy before surfacing your site in regulated industries (health, finance, legal, e-commerce). A missing privacy policy lowers your trust score and may cause AI systems to exclude your site from recommendations where data handling transparency is required.',\n fix: 'Create a dedicated privacy policy page at /privacy-policy/ or /privacy/. Cover data collection practices, cookie usage, third-party data sharing, and user rights under GDPR/CCPA.',\n code: '<!-- Create /privacy-policy/ with these key sections:\\n 1. What data you collect\\n 2. How you use cookies and tracking\\n 3. Third-party data sharing\\n 4. User rights (access, deletion, opt-out)\\n 5. Contact information for privacy inquiries -->',\n effort: 'moderate',\n tags: ['trust', 'legal', 'compliance'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const page = ctx.pages?.[0];\n const privacyPaths = ['/privacy-policy/', '/privacy/', '/privacy-policy', '/privacy'];\n const found = privacyPaths.find((p) => ctx.rootFiles[p] && ctx.rootFiles[p].status === 200);\n\n if (found) {\n return this.pass(\n `Privacy policy found at ${found}.`,\n '/privacy-policy/ or /privacy/ returns 200',\n `${found} — status 200`,\n page?.url,\n );\n }\n\n // Fallback: a privacy policy linked at a non-standard path (e.g.\n // /customer-service/.../privacy-policy.html) — how search engines find it.\n const linked = findPrivacyLink(ctx);\n if (linked) {\n return this.pass(\n `Privacy policy linked at ${linked}.`,\n 'A discoverable link to a privacy policy page',\n linked,\n page?.url,\n );\n }\n\n const statuses = privacyPaths\n .map((p) => {\n const file = ctx.rootFiles[p];\n return `${p}: ${file ? `status ${file.status}` : 'not fetched'}`;\n })\n .join('; ');\n\n return this.fail(\n 'No privacy policy page found. A privacy policy builds trust with users and AI agents.',\n '/privacy-policy/ or /privacy/ returns 200',\n statuses,\n {\n priority: 'medium',\n description:\n 'Enterprise AI frameworks check for privacy policies before recommending sites in regulated industries. A missing privacy policy reduces your trust score in AI systems that prioritize sites with transparent data handling practices, especially for health, finance, and legal content.',\n code: '<!-- Create a page at /privacy-policy/ or /privacy/ with sections covering:\\n - Data collection practices\\n - Cookie usage\\n - Third-party sharing\\n - User rights (GDPR/CCPA) -->',\n },\n page?.url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\n// Match a terms link by anchor text or href (terms of service/use, terms &\n// conditions, conditions of use, /tos), without over-matching unrelated text.\nconst TERMS_TEXT =\n /\\bterms\\s*(of\\s*(service|use|sale)|&\\s*conditions|and\\s*conditions)\\b|\\bconditions\\s*of\\s*use\\b/;\nconst TERMS_HREF =\n /terms[-_](of[-_](service|use|sale)|and[-_]conditions|conditions)|\\/terms(\\.[a-z0-9]+)?($|[/?#])|\\/tos($|[/?#])/;\n\n/** Find a linked terms-of-service page anywhere in the scanned pages' anchors. */\nfunction findTermsLink(ctx: CheckContext): string | null {\n for (const page of ctx.pages) {\n let hit: string | null = null;\n page.$('a[href]').each((_, el) => {\n if (hit) return;\n /* v8 ignore next */\n const href = (page.$(el).attr('href') ?? '').trim();\n if (!href) return;\n const text = page.$(el).text().trim().toLowerCase();\n if (\n text === 'terms' ||\n text === 'terms & conditions' ||\n TERMS_TEXT.test(text) ||\n TERMS_HREF.test(href.toLowerCase())\n ) {\n hit = href;\n }\n });\n if (hit) return hit;\n }\n return null;\n}\n\nexport class TermsOfServiceAudit extends Audit {\n static override meta: AuditMeta = {\n id: '8.20',\n category: 'technical-readiness',\n title: 'Terms of service exists',\n failureTitle: 'Terms of service exists',\n description:\n 'AI agents check for terms of service to determine whether automated access is permitted. A missing ToS page creates legal ambiguity that may cause enterprise AI systems to avoid recommending your site. Clear terms also let you specify AI usage policies for your content.',\n scoreDisplayMode: 'binary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'AI agents check for terms of service to determine whether automated access and content usage are permitted. A missing ToS creates legal ambiguity that causes enterprise AI systems to deprioritize your site to avoid compliance risk. Clear terms also let you explicitly define AI usage policies for your content.',\n fix: 'Create a terms of service page at /terms/ covering acceptable use, AI/automated access policy, content licensing, and liability limitations. Consider adding an explicit section on AI agent access and content reuse permissions.',\n code: '<!-- Create /terms/ with these key sections:\\n 1. Acceptable use policy\\n 2. AI and automated access policy\\n 3. Content licensing and reuse terms\\n 4. Liability limitations\\n 5. Termination conditions -->',\n effort: 'moderate',\n tags: ['trust', 'legal', 'compliance'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const page = ctx.pages?.[0];\n const termsPaths = ['/terms/', '/terms'];\n const found = termsPaths.find((p) => ctx.rootFiles[p] && ctx.rootFiles[p].status === 200);\n\n if (found) {\n return this.pass(\n `Terms of service found at ${found}.`,\n '/terms/ or /terms returns 200',\n `${found} — status 200`,\n page?.url,\n );\n }\n\n // Fallback: terms linked at a non-standard path (e.g.\n // /terms-and-conditions.html) — how search engines actually find it.\n const linked = findTermsLink(ctx);\n if (linked) {\n return this.pass(\n `Terms of service linked at ${linked}.`,\n 'A discoverable link to a terms page',\n linked,\n page?.url,\n );\n }\n\n const file = ctx.rootFiles['/terms/'] ?? ctx.rootFiles['/terms'];\n\n return this.fail(\n 'No terms of service page found. Terms of service establish usage rules for visitors and AI agents.',\n '/terms/ returns 200',\n file ? `Status ${file.status}` : 'Not fetched',\n {\n priority: 'medium',\n description:\n 'AI agents check for terms of service to determine whether automated access is permitted. A missing ToS page creates legal ambiguity that may cause enterprise AI systems to avoid recommending your site. Clear terms also let you specify AI usage policies for your content.',\n code: '<!-- Create a page at /terms/ with sections covering:\\n - Acceptable use\\n - AI/automated access policy\\n - Content licensing\\n - Liability limitations -->',\n },\n page?.url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class FrameworkDetectionAudit extends Audit {\n static override meta: AuditMeta = {\n id: '8.21',\n category: 'technical-readiness',\n title: 'Frontend framework detection',\n failureTitle: 'Frontend framework detection',\n description:\n 'AI agents can optimize their interaction strategy if they know the underlying technology stack (e.g., React, Next.js, Vue). This also helps identify potential client-side rendering issues.',\n scoreDisplayMode: 'informative',\n weight: 1.0,\n defaultPriority: 'low',\n guidance: {\n impact:\n 'This is an informational audit. Knowing your frontend framework helps identify potential rendering issues — for example, pure client-side React apps are invisible to AI crawlers that do not execute JavaScript. Framework detection also helps prioritize other audit recommendations.',\n fix: 'No action required. This audit detects your framework automatically. If your framework relies on client-side rendering (e.g., Create React App, Vue SPA), consider switching to a server-rendering mode (Next.js, Nuxt, or SvelteKit) so AI crawlers can read your content.',\n effort: 'trivial',\n tags: ['informational', 'framework'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const page = ctx.pages[0];\n if (!page) {\n return this.fail('No pages available for analysis.', '', 'None');\n }\n\n const { meta, $ } = page;\n const frameworks: string[] = [];\n\n // 1. Meta tag detection\n if (meta['generator']) {\n frameworks.push(`Generator: ${meta['generator']}`);\n }\n if (meta['next-head-count'] || $('script[id=\"__NEXT_DATA__\"]').length > 0) {\n frameworks.push('Next.js');\n }\n if (\n $('script[src*=\"nuxt\"]').length > 0 ||\n (globalThis as { window?: { __NUXT__?: unknown } }).window?.__NUXT__\n ) {\n frameworks.push('Nuxt.js');\n }\n\n // 2. Script/Data attributes\n if ($('[data-reactroot], [data-reactid]').length > 0 || $('script[src*=\"react\"]').length > 0) {\n frameworks.push('React');\n }\n if ($('[data-v-field], [data-v-]').length > 0 || $('script[src*=\"vue\"]').length > 0) {\n frameworks.push('Vue.js');\n }\n if ($('app-root, [ng-version]').length > 0) {\n frameworks.push('Angular');\n }\n if ($('script[src*=\"astro\"]').length > 0 || $('style[data-astro-cid]').length > 0) {\n frameworks.push('Astro');\n }\n if ($('script[src*=\"svelte\"]').length > 0) {\n frameworks.push('Svelte');\n }\n\n if (frameworks.length > 0) {\n const unique = Array.from(new Set(frameworks));\n return this.pass(\n `Detected frameworks: ${unique.join(', ')}.`,\n 'Identify the frontend framework used by the site.',\n unique.join(', '),\n );\n }\n\n return this.pass(\n 'No specific frontend framework clearly detected.',\n 'Identify the frontend framework used by the site.',\n 'Generic/Unknown',\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext, PageContext } from '../../check-context';\nimport { extractHeadings, flattenJsonLd } from '../../parser';\n\n// Matches FAQ section labels in headings/summaries: \"Frequently Asked\n// Questions\", \"FAQ(s)\", \"Common Questions\", \"Questions & Answers\", \"Q&A\".\nconst FAQ_TEXT =\n /frequently\\s+asked\\s+questions|\\bFAQ['']?s?\\b|common\\s+questions|questions?\\s*(?:&|and)\\s*answers|\\bQ\\s*&\\s*A\\b/i;\n\n/** True when the page carries FAQPage JSON-LD (robust to nesting/@graph). */\nfunction hasFaqJsonLd(p: PageContext): boolean {\n for (const node of flattenJsonLd(p.structuredData ?? p.jsonLd)) {\n const t = (node as Record<string, unknown>)['@type'];\n if (typeof t === 'string' && /faqpage/i.test(t)) return true;\n if (Array.isArray(t) && t.some((x) => typeof x === 'string' && /faqpage/i.test(x))) return true;\n }\n return false;\n}\n\nexport class FaqSectionsAudit extends Audit {\n static override meta: AuditMeta = {\n id: '9.1',\n category: 'answer-engine',\n title: 'FAQ sections present',\n failureTitle: 'FAQ sections present',\n description:\n 'AI answer engines like Perplexity extract FAQ-structured content with higher confidence for direct answers. FAQ sections with clear question headings are the top extraction target for \"People Also Ask\" results and conversational AI responses.',\n scoreDisplayMode: 'binary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'FAQ sections with clear question headings are the highest-priority extraction target for AI-generated answers and \"People Also Ask\" results. Without them, your content misses the most direct path to appearing in AI answer snippets.',\n fix: 'Add a \"Frequently Asked Questions\" section with question-formatted H3 headings, each followed immediately by a concise answer paragraph.',\n code: '<h2>Frequently Asked Questions</h2>\\n<h3>What is your return policy?</h3>\\n<p>We offer a 30-day money-back guarantee on all products.</p>\\n<h3>How long does shipping take?</h3>\\n<p>Standard shipping takes 3-5 business days within the US.</p>',\n effort: 'easy',\n tags: ['content-structure', 'faq', 'answer-engine'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const page = ctx.pages[0];\n if (!page) {\n return this.fail(\n 'No pages scanned.',\n 'Headings containing \"Frequently Asked Questions\" or \"FAQ\"',\n 'No pages scanned',\n {\n priority: 'medium',\n description: FaqSectionsAudit.meta.description,\n code: '<h2>Frequently Asked Questions</h2>\\n<h3>What is your return policy?</h3>\\n<p>We offer a 30-day money-back guarantee on all products.</p>',\n },\n );\n }\n\n for (const p of ctx.pages) {\n const $ = p.$;\n\n // 1. FAQPage structured data — the strongest signal.\n if (hasFaqJsonLd(p)) {\n return this.pass(\n 'Found FAQPage structured data (JSON-LD).',\n 'FAQ heading, FAQPage JSON-LD, or an accordion of questions',\n 'FAQPage JSON-LD',\n p.url,\n );\n }\n\n // 2. Heading / summary text matching FAQ phrasings.\n const headings = extractHeadings($);\n const faqHeadings = headings.filter((h) => FAQ_TEXT.test(h.text));\n const faqSummaries: string[] = [];\n $('details summary, summary').each((_, el) => {\n const t = $(el).text().trim();\n if (FAQ_TEXT.test(t)) faqSummaries.push(t);\n });\n const labels = [...faqHeadings.map((h) => h.text), ...faqSummaries];\n if (labels.length > 0) {\n return this.pass(\n `Found ${labels.length} FAQ label(s): \"${labels[0]}\".`,\n 'FAQ heading, FAQPage JSON-LD, or an accordion of questions',\n labels.join('; '),\n p.url,\n );\n }\n\n // 3. FAQ accordions: class/id containing \"faq\", or <details>/<summary>\n // whose summaries read as questions.\n const faqAccordions = $('[class], [id]').filter((_, el) => {\n const cls = ($(el).attr('class') ?? '').toLowerCase();\n const id = ($(el).attr('id') ?? '').toLowerCase();\n return /faq/.test(cls) || /faq/.test(id);\n });\n const questionSummaries = $('details summary').filter((_, el) =>\n /\\?\\s*$/.test($(el).text().trim()),\n );\n if (faqAccordions.length > 0 || questionSummaries.length > 0) {\n const detail =\n faqAccordions.length > 0\n ? `${faqAccordions.length} FAQ container(s)`\n : `${questionSummaries.length} question accordion(s)`;\n return this.pass(\n `Found an FAQ-style accordion (${detail}).`,\n 'FAQ heading, FAQPage JSON-LD, or an accordion of questions',\n detail,\n p.url,\n );\n }\n }\n\n return this.fail(\n 'No FAQ sections found (headings, FAQPage JSON-LD, or accordions).',\n 'FAQ heading, FAQPage JSON-LD, or an accordion of questions',\n 'Not found',\n {\n priority: 'medium',\n description:\n 'FAQ sections with clear question headings are the highest-priority extraction target for AI-generated answers. Structure each Q&A with a question heading followed by a direct answer paragraph.',\n code: '<h2>Frequently Asked Questions</h2>\\n<h3>What is your return policy?</h3>\\n<p>We offer a 30-day money-back guarantee on all products.</p>\\n<h3>How long does shipping take?</h3>\\n<p>Standard shipping takes 3-5 business days within the US.</p>',\n },\n page.url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\nimport { extractHeadings } from '../../parser';\n\nexport class QuestionHeadingsAudit extends Audit {\n static override meta: AuditMeta = {\n id: '9.2',\n category: 'answer-engine',\n title: 'Question-formatted headings',\n failureTitle: 'Question-formatted headings',\n description:\n 'AI answer engines directly match user questions to heading text. Question-formatted headings (ending with \"?\") are the primary signal AI systems use to identify which section answers a specific query.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n \"AI answer engines directly match user questions to heading text. Question-formatted headings are the primary signal for identifying which section answers a specific query. Without them, agents must guess which section is relevant, reducing your content's match rate.\",\n fix: 'Reformat H2/H3 headings as questions that end with \"?\" to match the natural language patterns users ask AI agents. Follow each question heading immediately with a direct answer paragraph.',\n code: '<h2>What is unified content preparation?</h2>\\n<p>Unified content preparation is the process of structuring your site content for consumption by both humans and AI agents.</p>',\n effort: 'easy',\n tags: ['content-structure', 'copywriting', 'answer-engine'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const page = ctx.pages[0];\n if (!page) {\n return this.fail('No pages scanned.', 'H2/H3 headings ending with \"?\"', 'No pages scanned', {\n priority: 'medium',\n description: QuestionHeadingsAudit.meta.description,\n code: '<h2>What is unified content preparation?</h2>\\n<p>Unified content preparation is...</p>',\n });\n }\n\n let questionCount = 0;\n let totalH2H3 = 0;\n const examples: string[] = [];\n\n for (const p of ctx.pages) {\n const headings = extractHeadings(p.$);\n for (const h of headings) {\n if (h.level === 2 || h.level === 3) {\n totalH2H3++;\n if (h.text.trimEnd().endsWith('?')) {\n questionCount++;\n if (examples.length < 3) {\n examples.push(h.text);\n }\n }\n }\n }\n }\n\n if (questionCount >= 2) {\n return this.pass(\n `Found ${questionCount} question-formatted H2/H3 heading(s).`,\n 'H2/H3 headings ending with \"?\"',\n examples.join('; '),\n page.url,\n );\n }\n\n if (questionCount === 1) {\n return this.warn(\n `Only 1 question-formatted heading found out of ${totalH2H3} H2/H3 headings.`,\n 'H2/H3 headings ending with \"?\"',\n examples.join('; '),\n {\n priority: 'medium',\n description:\n 'Adding more question-formatted H2/H3 headings increases the number of user queries your content can match, boosting your visibility in AI-generated answers and \"People Also Ask\" results.',\n code: '<h2>How does your product compare to alternatives?</h2>\\n<h2>What are the system requirements?</h2>',\n },\n page.url,\n );\n }\n\n return this.fail(\n `No question-formatted H2/H3 headings found across ${ctx.pages.length} page(s).`,\n 'H2/H3 headings ending with \"?\"',\n 'Not found',\n {\n priority: 'medium',\n description:\n 'Question-formatted headings (\"What is X?\", \"How does Y work?\") are the primary signal for identifying which section answers a query. Each question heading should be followed immediately by a direct answer paragraph.',\n code: '<h2>What is unified content preparation?</h2>\\n<p>Unified content preparation is the process of structuring your site content for consumption by both humans and AI agents.</p>',\n },\n page.url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext, PageContext } from '../../check-context';\nimport { getMainContentText, flattenJsonLd } from '../../parser';\n\n// Broad visible-date matcher. Covers: numeric DD/MM/YYYY & ISO YYYY-MM-DD\n// (with optional time component, e.g. 2025-04-02T10:00:00Z — the old trailing\n// \\b broke right before the \"T\"), \"Month DD, YYYY\", UK/EU \"DD Month YYYY\",\n// bare \"Month YYYY\", the 4-letter \"Sept\" abbreviation, and relative phrases\n// (\"3 days ago\"). Kept identical across dates-on-content / last-updated /\n// publication-date so the three freshness audits agree.\nconst DATE_PATTERN =\n /\\b(?:\\d{4}[/-]\\d{1,2}[/-]\\d{1,2}(?:[T ]\\d{2}:\\d{2}(?::\\d{2})?(?:\\.\\d+)?Z?)?|\\d{1,2}[/-]\\d{1,2}[/-]\\d{2,4}|(?:January|February|March|April|May|June|July|August|September|October|November|December|Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sept?|Oct|Nov|Dec)\\s+\\d{1,2},?\\s+\\d{4}|\\d{1,2}\\s+(?:January|February|March|April|May|June|July|August|September|October|November|December|Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sept?|Oct|Nov|Dec)\\s+\\d{4}|(?:January|February|March|April|May|June|July|August|September|October|November|December|Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sept?|Oct|Nov|Dec)\\s+\\d{4}|\\d+\\s+(?:day|week|month|year)s?\\s+ago)\\b/i;\n\n/**\n * Only run freshness checks on genuine article pages. Excludes XML sitemaps\n * (Shopify exposes `…/sitemap_products_1.xml` as pageType \"content\") and other\n * non-HTML interstitials, which have no meaningful publication date.\n */\nexport function isArticleContentPage(p: PageContext): boolean {\n if (p.pageType !== 'content') return false;\n let pathname = '';\n try {\n pathname = new URL(p.url).pathname.toLowerCase();\n } catch {\n pathname = '';\n }\n if (pathname.endsWith('.xml')) return false;\n /* v8 ignore next -- FetchResult.body is typed as required string; null guard is defensive */\n const head = (p.fetchResult.body ?? '').slice(0, 256).trimStart().toLowerCase();\n if (head.startsWith('<?xml') || head.startsWith('<urlset') || head.startsWith('<sitemapindex')) {\n return false;\n }\n return true;\n}\n\n/** Pull a publication/modification date from JSON-LD, robust to nesting. */\nexport function findJsonLdDate(jsonLd: object[]): string | null {\n for (const node of flattenJsonLd(jsonLd)) {\n const n = node as Record<string, unknown>;\n const v = n['datePublished'] ?? n['dateModified'] ?? n['uploadDate'] ?? n['dateCreated'];\n if (typeof v === 'string' && v.trim()) return v.trim();\n }\n return null;\n}\n\n/**\n * Resolve a date from structured sources, in priority order:\n * 1. <time datetime> 2. JSON-LD 3. <meta article:*_time> 4. bare <time>.\n * These are machine-readable and far more reliable than scraping body text —\n * e.g. mejuri's blog article exposes datePublished only in JSON-LD/meta.\n */\nexport function findStructuredDate(\n p: PageContext,\n): { value: string; source: string } | null {\n const timeWithAttr = p.$('time[datetime]').first();\n if (timeWithAttr.length) {\n /* v8 ignore next -- time[datetime] selector guarantees the attr exists; ?? fallback is unreachable */\n return { value: timeWithAttr.attr('datetime') ?? timeWithAttr.text().trim(), source: '<time datetime>' };\n }\n const jsonDate = findJsonLdDate(p.jsonLd);\n if (jsonDate) return { value: jsonDate, source: 'JSON-LD' };\n const metaDate =\n p.meta['article:published_time'] ??\n p.meta['article:modified_time'] ??\n p.meta['og:updated_time'];\n if (metaDate?.trim()) return { value: metaDate.trim(), source: 'meta' };\n const anyTime = p.$('time').first();\n if (anyTime.length) {\n const v = anyTime.attr('datetime') ?? anyTime.text().trim();\n if (v) return { value: v, source: '<time>' };\n }\n return null;\n}\n\nexport class DatesOnContentAudit extends Audit {\n static override meta: AuditMeta = {\n id: '9.8',\n category: 'answer-engine',\n title: 'Dates on content pages',\n failureTitle: 'Dates on content pages',\n description:\n 'AI engines use dates to assess content freshness. Undated content is deprioritized in AI answers because agents cannot verify its recency.',\n scoreDisplayMode: 'binary',\n weight: 1.0,\n applicablePageTypes: ['content'],\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'AI answer engines use publication dates to assess content freshness for recency-weighted ranking. Undated content is deprioritized because agents cannot verify whether the information is current, especially for queries where timeliness matters.',\n fix: 'Add a visible date using the <time> element with a machine-readable datetime attribute on every content page. Place it near the article title or byline.',\n code: '<p>Published: <time datetime=\"2025-01-15\">January 15, 2025</time></p>',\n effort: 'trivial',\n tags: ['freshness', 'html', 'answer-engine'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const contentPages = ctx.pages.filter(isArticleContentPage);\n if (contentPages.length === 0) {\n return this.notApplicable(\n 'No article content pages were scanned, so content freshness dates do not apply.',\n '<time> elements or visible date patterns present',\n 'No content pages',\n );\n }\n\n for (const p of contentPages) {\n const structured = findStructuredDate(p);\n if (structured) {\n return this.pass(\n `Found a structured date (${structured.source}).`,\n '<time> elements or visible date patterns present',\n `${structured.source}: \"${structured.value}\"`,\n p.url,\n );\n }\n\n const text = getMainContentText(p.$);\n const dateMatch = text.match(DATE_PATTERN);\n if (dateMatch) {\n return this.pass(\n 'Visible date pattern found in content.',\n '<time> elements or visible date patterns present',\n dateMatch[0],\n p.url,\n );\n }\n }\n\n return this.fail(\n 'No dates found on scanned content pages.',\n '<time> elements or visible date patterns present',\n 'Not found',\n {\n priority: 'medium',\n description:\n 'AI answer engines use publication dates to assess content freshness for recency-weighted ranking. Undated content is deprioritized because agents cannot verify whether the information is current, especially for queries where timeliness matters.',\n code: '<p>Published: <time datetime=\"2025-01-15\">January 15, 2025</time></p>',\n },\n contentPages[0].url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\nimport { isArticleContentPage } from './dates-on-content';\n\nconst WEAK_OPENERS = [\n /^in this (article|post|guide|page)/i,\n /^welcome/i,\n /^(what|how|why|when|where|who|which|can|do|does|is|are|will|should)\\b.*\\?$/i,\n /^have you ever/i,\n /^did you know/i,\n];\n\nexport class FirstParagraphAnswersAudit extends Audit {\n static override meta: AuditMeta = {\n id: '9.3',\n category: 'answer-engine',\n title: 'First paragraph answers primary question',\n failureTitle: 'First paragraph answers primary question',\n description:\n 'AI search engines score the first paragraph highest for extractive QA. Preamble text like \"In this article\" or \"Welcome\" wastes this prime position, causing agents to extract low-value content as your page\\'s representative answer.',\n scoreDisplayMode: 'binary',\n weight: 1.0,\n applicablePageTypes: ['content'],\n defaultPriority: 'high',\n guidance: {\n impact:\n 'AI search engines score the first paragraph highest for extractive QA. Preamble text like \"In this article\" or \"Welcome\" wastes this prime position, causing agents to extract low-value filler as your page\\'s representative answer.',\n fix: 'Rewrite the first paragraph in <main> as a direct, declarative answer to the page\\'s primary question. Remove preamble phrases like \"In this article\", \"Welcome\", or rhetorical questions.',\n code: '<main>\\n <p>Unified content preparation optimizes your site for AI agents by structuring content with semantic HTML, JSON-LD, and machine-readable metadata.</p>\\n</main>',\n effort: 'easy',\n tags: ['content-quality', 'copywriting', 'answer-engine'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n // Only meaningful on article/content pages: on a JS storefront homepage the\n // first <p> in source order is utility chrome (\"Search\", \"Redirecting…\"),\n // which used to false-pass this check.\n const page = ctx.pages.find(isArticleContentPage);\n if (!page) {\n return this.notApplicable(\n 'No article content pages were scanned, so the first-paragraph check does not apply.',\n 'First substantive <p> on a content page is a declarative answer, not a filler intro',\n 'No content pages',\n );\n }\n\n const $ = page.$;\n const mainEl = $('main').first();\n const container = mainEl.length ? mainEl : $('body');\n\n // Pick the first SUBSTANTIVE paragraph: skip empty/short utility paragraphs\n // (nav, breadcrumbs, cookie banners) by requiring real prose — ≥15 words\n // and at least one sentence terminator.\n let firstP = '';\n container.find('p').each((_, el) => {\n const t = $(el).text().replace(/\\s+/g, ' ').trim();\n const wordCount = t.split(/\\s+/).filter(Boolean).length;\n if (wordCount >= 15 && /[a-z][.!?](\\s|$|[\"'’”)])/.test(t)) {\n firstP = t;\n return false;\n }\n return undefined;\n });\n\n if (!firstP) {\n return this.fail(\n 'No substantive opening paragraph found in the main content area.',\n 'First substantive <p> on a content page is a declarative answer, not a filler intro',\n 'No substantive <p> found',\n {\n priority: 'high',\n description:\n 'Without a substantive first paragraph, agents have no candidate answer to extract from your page. Add a direct, declarative opening paragraph to your main content area.',\n code: '<main>\\n <p>Your direct answer to the page topic goes here as the first paragraph.</p>\\n</main>',\n },\n page.url,\n );\n }\n\n const isWeak = WEAK_OPENERS.some((pattern) => pattern.test(firstP));\n\n if (!isWeak) {\n return this.pass(\n 'First paragraph appears to be a direct, declarative answer.',\n 'First substantive <p> on a content page is a declarative answer, not a filler intro',\n firstP.length > 120 ? firstP.slice(0, 120) + '...' : firstP,\n page.url,\n );\n }\n\n return this.fail(\n 'First paragraph starts with a weak opener instead of a direct answer.',\n 'First substantive <p> on a content page is a declarative answer, not a filler intro',\n firstP.length > 120 ? firstP.slice(0, 120) + '...' : firstP,\n {\n priority: 'high',\n description:\n \"Rewrite the first paragraph as a direct, declarative answer to the page's primary question. Preamble text causes agents to extract low-value filler as your page's representative answer.\",\n code: '<!-- Instead of \"In this article, we explore...\" use: -->\\n<p>Content preparation for AI agents involves structuring your pages with semantic HTML, adding JSON-LD schema, and providing machine-readable metadata.</p>',\n },\n page.url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\nimport { isArticleContentPage } from './dates-on-content';\n\nconst wordCount = (s: string): number => s.split(/\\s+/).filter(Boolean).length;\n\nexport class DirectDefinitionsAudit extends Audit {\n static override meta: AuditMeta = {\n id: '9.4',\n category: 'answer-engine',\n title: 'Direct definitions for key terms',\n failureTitle: 'Direct definitions for key terms',\n description:\n 'AI engines extract term-definition pairs to generate direct-answer snippets for \"what is X?\" queries. Use <dfn>, <dl>, or bold-colon patterns to mark up key terms.',\n scoreDisplayMode: 'binary',\n weight: 1.0,\n applicablePageTypes: ['content'],\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'AI engines extract term-definition pairs to generate direct-answer snippets for \"what is X?\" queries. Without explicit definition markup, agents must infer definitions from surrounding text, reducing your chances of being selected as a direct answer.',\n fix: 'Use <dfn>, <dl>/<dt>/<dd>, or bold-colon patterns (\"<strong>Term:</strong> definition\") to mark up key terms and their definitions throughout your content.',\n code: '<dl>\\n <dt><dfn>Unified Content Preparation</dfn></dt>\\n <dd>The process of structuring site content for consumption by both humans and AI agents.</dd>\\n</dl>',\n effort: 'easy',\n tags: ['content-structure', 'html', 'answer-engine'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n // Scope to article content. On product pages, \"<strong>Weight:</strong> 200g\"\n // spec labels look like definitions but are not — so we require the markup\n // to introduce a real, sentence-length definition.\n const contentPages = ctx.pages.filter(isArticleContentPage);\n if (contentPages.length === 0) {\n return this.notApplicable(\n 'No article content pages were scanned, so definition formatting does not apply.',\n 'Definition-style formatting (<dfn>, sentence-length <dl>, or bold-colon + sentence)',\n 'No content pages',\n );\n }\n\n const signals: string[] = [];\n\n for (const p of contentPages) {\n const $ = p.$;\n\n // <dfn> is unambiguous definition markup.\n const dfnCount = $('dfn').length;\n if (dfnCount > 0) {\n signals.push(`<dfn> (${dfnCount})`);\n }\n\n // <dl> only counts when at least one <dd> is sentence-length — product\n // spec tables (\"Weight: 200g\") have terse, fragment <dd> values.\n let sentenceDd = 0;\n $('dl dd').each((_, el) => {\n const t = $(el).text().replace(/\\s+/g, ' ').trim();\n if (wordCount(t) >= 6) sentenceDd++;\n });\n if (sentenceDd > 0) {\n signals.push(`<dl> with sentence definitions (${sentenceDd})`);\n }\n\n // Bold-colon (\"<strong>Term:</strong> …\") counts only when the text that\n // FOLLOWS the colon is a sentence, not a short spec value.\n let boldColonDefs = 0;\n $('strong, b').each((_, el) => {\n const label = $(el).text().replace(/\\s+/g, ' ').trim();\n if (!label.endsWith(':')) return;\n const parentText = $(el).parent().text().replace(/\\s+/g, ' ').trim();\n const after = parentText.slice(parentText.indexOf(label) + label.length).trim();\n if (wordCount(after) >= 6) boldColonDefs++;\n });\n if (boldColonDefs > 0) {\n signals.push(`bold-colon definitions (${boldColonDefs})`);\n }\n }\n\n if (signals.length > 0) {\n return this.pass(\n `Definition-style formatting found: ${signals.join(', ')}.`,\n 'Definition-style formatting (<dfn>, sentence-length <dl>, or bold-colon + sentence)',\n signals.join(', '),\n contentPages[0].url,\n );\n }\n\n return this.fail(\n 'No definition-style formatting found (<dfn>, sentence-length <dl>, or bold-colon + sentence).',\n 'Definition-style formatting (<dfn>, sentence-length <dl>, or bold-colon + sentence)',\n 'Not found',\n {\n priority: 'medium',\n description:\n 'AI engines use <dfn>, <dl>, and bold-colon patterns (\"**Term:** definition\") to extract term-definition pairs for \"what is X?\" answer snippets. Without explicit definition markup, agents must infer definitions from surrounding text, which is less reliable and reduces your content\\'s chances of being selected as a direct answer.',\n code: '<dl>\\n <dt><dfn>Unified Content Preparation</dfn></dt>\\n <dd>The process of structuring site content for consumption by both humans and AI agents.</dd>\\n</dl>',\n },\n contentPages[0].url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class ComparisonTablesAudit extends Audit {\n static override meta: AuditMeta = {\n id: '9.5',\n category: 'answer-engine',\n title: 'Comparison tables present',\n failureTitle: 'Comparison tables present',\n description:\n 'AI answer engines extract structured table data to generate comparison answers. Add HTML tables to your content where appropriate.',\n scoreDisplayMode: 'binary',\n weight: 1.0,\n applicablePageTypes: ['category', 'product', 'content'],\n defaultPriority: 'low',\n guidance: {\n impact:\n 'AI answer engines extract structured table data to generate comparison answers for queries like \"What is the difference between X and Y?\" Without HTML tables, your comparison content is harder for agents to parse and less likely to appear as a structured answer.',\n fix: 'Add HTML <table> elements with proper <thead> and <th> headers for any comparative content on your pages. Ensure each column has a descriptive header.',\n code: '<table>\\n <thead>\\n <tr><th>Feature</th><th>Plan A</th><th>Plan B</th></tr>\\n </thead>\\n <tbody>\\n <tr><td>Price</td><td>$10/mo</td><td>$20/mo</td></tr>\\n <tr><td>Storage</td><td>10 GB</td><td>50 GB</td></tr>\\n </tbody>\\n</table>',\n effort: 'easy',\n tags: ['content-structure', 'html', 'answer-engine'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const page = ctx.pages[0];\n if (!page) {\n return this.fail(\n 'No pages scanned.',\n '<table> elements with comparison data',\n 'No pages scanned',\n {\n priority: 'low',\n description: ComparisonTablesAudit.meta.description,\n code: '<table>\\n <thead><tr><th>Feature</th><th>Plan A</th><th>Plan B</th></tr></thead>\\n <tbody><tr><td>Price</td><td>$10</td><td>$20</td></tr></tbody>\\n</table>',\n },\n );\n }\n\n let tableCount = 0;\n let pageWithTable: string | undefined;\n\n for (const p of ctx.pages) {\n const tables = p.$('table').length;\n if (tables > 0) {\n tableCount += tables;\n if (!pageWithTable) {\n pageWithTable = p.url;\n }\n }\n }\n\n if (tableCount > 0) {\n return this.pass(\n `Found ${tableCount} table(s) across scanned pages.`,\n '<table> elements with comparison data',\n `${tableCount} table(s)`,\n pageWithTable,\n );\n }\n\n return this.fail(\n 'No comparison tables found on any scanned page.',\n '<table> elements with comparison data',\n 'Not found',\n {\n priority: 'low',\n description:\n 'AI answer engines extract HTML tables to generate structured comparison answers (\"What is the difference between X and Y?\"). Properly structured tables with <thead> and <th> are directly rendered in AI-generated responses, giving your content prime visibility in comparison queries.',\n code: '<table>\\n <thead><tr><th>Feature</th><th>Plan A</th><th>Plan B</th></tr></thead>\\n <tbody><tr><td>Price</td><td>$10</td><td>$20</td></tr></tbody>\\n</table>',\n },\n page.url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class NumberedStepsAudit extends Audit {\n static override meta: AuditMeta = {\n id: '9.6',\n category: 'answer-engine',\n title: 'Numbered steps for processes',\n failureTitle: 'Numbered steps for processes',\n description:\n 'AI engines extract <ol> lists for \"how to\" answer snippets. Use ordered lists for step-by-step content to improve your visibility in procedural AI-generated answers.',\n scoreDisplayMode: 'binary',\n weight: 1.0,\n applicablePageTypes: ['content'],\n defaultPriority: 'low',\n guidance: {\n impact:\n 'AI answer engines extract <ol> ordered lists for \"how to\" answer snippets, preserving step order in generated responses. Processes described in paragraph form are harder for agents to parse and less likely to appear as structured step-by-step answers.',\n fix: 'Convert any step-by-step or procedural content from paragraphs to <ol> ordered lists. Each <li> should describe one clear step.',\n code: '<h2>How to Get Started</h2>\\n<ol>\\n <li>Create an account at yoursite.com/signup</li>\\n <li>Configure your API key in the dashboard</li>\\n <li>Make your first API call using the quickstart guide</li>\\n</ol>',\n effort: 'easy',\n tags: ['content-structure', 'html', 'answer-engine'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const page = ctx.pages[0];\n if (!page) {\n return this.fail(\n 'No pages scanned.',\n '<ol> ordered lists present for process/step content',\n 'No pages scanned',\n {\n priority: 'low',\n description: NumberedStepsAudit.meta.description,\n code: '<ol>\\n <li>Step one</li>\\n <li>Step two</li>\\n</ol>',\n },\n );\n }\n\n let olCount = 0;\n let pageWithOl: string | undefined;\n\n for (const p of ctx.pages) {\n const ols = p.$('ol').length;\n if (ols > 0) {\n olCount += ols;\n if (!pageWithOl) {\n pageWithOl = p.url;\n }\n }\n }\n\n if (olCount > 0) {\n return this.pass(\n `Found ${olCount} ordered list(s) across scanned pages.`,\n '<ol> ordered lists present for process/step content',\n `${olCount} <ol> element(s)`,\n pageWithOl,\n );\n }\n\n return this.fail(\n 'No ordered lists found on any scanned page.',\n '<ol> ordered lists present for process/step content',\n 'Not found',\n {\n priority: 'low',\n description:\n 'AI answer engines extract <ol> ordered lists for \"how to\" answer snippets, preserving step order in generated responses. Processes described in paragraph form are harder for agents to parse and are less likely to appear as structured step-by-step answers.',\n code: '<ol>\\n <li>Step one</li>\\n <li>Step two</li>\\n <li>Step three</li>\\n</ol>',\n },\n page.url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\nimport { getMainContentText } from '../../parser';\n\n// A \"specific data point\" must carry a unit, a percent/currency symbol, a\n// grouped thousands separator, or be a small word-bounded range like \"3-5\n// days\". The old bare `\\d+\\s*[-–]\\s*\\d+` branch matched timestamps, phone\n// numbers and SKUs (e.g. \"555-123-4567\", \"12-34-5678\"), producing junk\n// \"examples\" — those no longer qualify because nothing here matches a raw\n// number with no unit/symbol.\nconst UNIT =\n '(?:%|kg|kgs|g|mg|lbs?|oz|cm|mm|km|in|ft|hrs?|hours?|mins?|minutes?|seconds?|secs?|days?|weeks?|months?|years?|ml|cl|l|liters?|litres?|gb|mb|tb|k|million|billion|degrees?|x|mph|reps?|sets?|calories?|cal)';\nconst DATA_PATTERN = new RegExp(\n // percentage\n '\\\\d+(?:\\\\.\\\\d+)?\\\\s*%' +\n // currency amount\n '|[$€£¥]\\\\s?\\\\d[\\\\d,]*(?:\\\\.\\\\d+)?' +\n // ranges with a unit (\"3-5 business days\", \"10–15 minutes\")\n '|\\\\b\\\\d{1,4}\\\\s*[-–—]\\\\s*\\\\d{1,4}(?:\\\\s+\\\\w+)?\\\\s+' +\n UNIT +\n '\\\\b' +\n // hyphenated unit (\"30-day\", \"24-hour\")\n '|\\\\b\\\\d{1,4}-' +\n UNIT +\n '\\\\b' +\n // grouped thousands (\"10,000\", \"50,000\")\n '|\\\\b\\\\d{1,3}(?:,\\\\d{3})+(?:\\\\.\\\\d+)?\\\\b' +\n // number directly followed by a unit (\"200g\", \"99.9%\", \"5 days\")\n '|\\\\b\\\\d+(?:\\\\.\\\\d+)?\\\\s*' +\n UNIT +\n '\\\\b',\n);\n\nexport class SpecificNumbersAudit extends Audit {\n static override meta: AuditMeta = {\n id: '9.7',\n category: 'answer-engine',\n title: 'Specific numbers and data points',\n failureTitle: 'Specific numbers and data points',\n description:\n 'AI engines prefer answers with concrete data points over vague statements. Include specific numbers, percentages, and metrics in your content.',\n scoreDisplayMode: 'binary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'AI answer engines strongly prefer content with concrete data points over vague claims. Pages with specific numbers, percentages, and metrics are ranked higher for data-driven queries because agents can cite exact figures in generated answers.',\n fix: 'Add specific numbers, percentages, dollar amounts, and measurable metrics throughout your content. Replace vague claims (\"significant improvement\") with concrete data (\"65% improvement\").',\n code: '<p>Our platform processes 50,000 requests per second with 99.9% uptime, reducing average response time by 65% compared to alternatives.</p>',\n effort: 'easy',\n tags: ['content-quality', 'copywriting', 'answer-engine'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const page = ctx.pages[0];\n if (!page) {\n return this.fail(\n 'No pages scanned.',\n 'Content contains digits, percentages, or dollar amounts',\n 'No pages scanned',\n {\n priority: 'medium',\n description: SpecificNumbersAudit.meta.description,\n code: '<p>Our platform reduces deployment time by 40%, serving 10,000+ daily requests at $0.01 per API call.</p>',\n },\n );\n }\n\n const matchingPages: string[] = [];\n const examples: string[] = [];\n\n for (const p of ctx.pages) {\n const text = getMainContentText(p.$);\n const matches = text.match(new RegExp(DATA_PATTERN.source, 'gi'));\n if (matches && matches.length > 0) {\n matchingPages.push(p.url);\n if (examples.length < 5) {\n examples.push(...matches.slice(0, 5 - examples.length));\n }\n }\n }\n\n if (matchingPages.length > 0) {\n return this.pass(\n `Specific data points found on ${matchingPages.length} page(s).`,\n 'Content contains digits, percentages, or dollar amounts',\n `Examples: ${examples.join(', ')}`,\n page.url,\n );\n }\n\n return this.fail(\n 'No specific numbers, percentages, or dollar amounts found in content.',\n 'Content contains digits, percentages, or dollar amounts',\n 'Not found',\n {\n priority: 'medium',\n description:\n 'AI answer engines strongly prefer content with concrete data points over vague claims. Pages with specific numbers, percentages, and metrics are ranked higher for data-driven queries because agents can cite exact figures in generated answers rather than paraphrasing vague language.',\n code: '<p>Our platform processes 50,000 requests per second with 99.9% uptime, reducing average response time by 65% compared to alternatives.</p>',\n },\n page.url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\nimport { getMainContentText } from '../../parser';\nimport type { CheerioAPI } from 'cheerio';\n\n/**\n * Word count of the main content, falling back to <body> when <main> is empty.\n * The plain getWordCount() picks <main> whenever the element merely exists —\n * but on JS/image-driven homepages <main> is often present yet empty, which\n * produced spurious \"insufficient content\" warnings.\n */\nfunction contentWordCount($: CheerioAPI): number {\n const main = $('main').first();\n const extract = (sel: ReturnType<CheerioAPI>): string => {\n const clone = sel.clone();\n clone.find('script, style, noscript, template').remove();\n return clone.text().replace(/\\s+/g, ' ').trim();\n };\n let text = main.length ? extract(main) : '';\n if (!text) text = extract($('body'));\n return text.split(/\\s+/).filter(Boolean).length;\n}\n\nconst TEASER_PATTERNS = [\n /click\\s+(here\\s+)?to\\s+read\\s+more/i,\n /contact\\s+us\\s+to\\s+learn/i,\n /sign\\s+up\\s+to\\s+(see|view|read|access)/i,\n /subscribe\\s+to\\s+(see|view|read|access|unlock)/i,\n /download\\s+(the\\s+)?(full|complete)\\s+(guide|report|whitepaper)/i,\n /register\\s+to\\s+(access|view|read)/i,\n /fill\\s+(out|in)\\s+(the\\s+)?form\\s+to/i,\n /get\\s+the\\s+full\\s+(story|details|report)/i,\n];\n\nexport class ContentWithoutClickthroughAudit extends Audit {\n static override meta: AuditMeta = {\n id: '9.9',\n category: 'answer-engine',\n title: 'Content answers without click-through',\n failureTitle: 'Content answers without click-through',\n description:\n 'AI answer engines skip teaser content that gates answers behind sign-ups or downloads. Provide substantive answers directly on the page.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'high',\n guidance: {\n impact:\n 'AI answer engines skip pages dominated by teaser content (\"click to read more\", \"sign up to access\"). These pages provide no extractable answers, so agents will never surface your content in AI-generated responses, costing you visibility in AI search.',\n fix: 'Replace gated teasers with substantive, self-contained answers directly on the page. Move lead-generation CTAs to secondary positions after the main content.',\n code: '<!-- Instead of: \"Download our guide to learn more\" -->\\n<h2>How It Works</h2>\\n<p>Our API supports REST and GraphQL endpoints with OAuth 2.0 authentication, processing up to 50,000 requests per second.</p>',\n effort: 'moderate',\n tags: ['content-quality', 'answer-engine'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const page = ctx.pages[0];\n if (!page) {\n return this.fail(\n 'No pages scanned.',\n 'No \"click to read more\" or \"contact us to learn\" teasers dominating the page',\n 'No pages scanned',\n {\n priority: 'high',\n description: ContentWithoutClickthroughAudit.meta.description,\n code: '<!-- Replace gated content with direct answers -->\\n<p>Our API supports REST and GraphQL endpoints with OAuth 2.0 authentication.</p>',\n },\n );\n }\n\n const teaserPages: Array<{ url: string; teasers: string[] }> = [];\n\n for (const p of ctx.pages) {\n const text = getMainContentText(p.$);\n const found: string[] = [];\n for (const pattern of TEASER_PATTERNS) {\n const match = text.match(pattern);\n if (match) {\n found.push(match[0]);\n }\n }\n if (found.length >= 2) {\n teaserPages.push({ url: p.url, teasers: found });\n }\n }\n\n if (teaserPages.length === 0) {\n // Low-content check, but never on the homepage: JS/image-driven storefront\n // homepages legitimately render little server-side text, so a word-count\n // warning there is noise. Evaluate a non-homepage page instead.\n const checkPage = ctx.pages.find((p) => {\n if (p.pageType === 'homepage') return false;\n let pathname = '';\n try {\n pathname = new URL(p.url).pathname.toLowerCase();\n } catch {\n pathname = '';\n }\n if (pathname.endsWith('.xml')) return false;\n /* v8 ignore next -- FetchResult.body is typed as required string; null guard is defensive */\n const head = (p.fetchResult.body ?? '').slice(0, 64).trimStart().toLowerCase();\n return !head.startsWith('<?xml');\n });\n if (checkPage) {\n const wordCount = contentWordCount(checkPage.$);\n if (wordCount < 50) {\n return this.warn(\n 'Insufficient content to evaluate.',\n 'No \"click to read more\" or \"contact us to learn\" teasers dominating the page',\n `Only ${wordCount} words on ${checkPage.url}`,\n {\n priority: 'medium',\n description:\n 'The page has very little content (fewer than 50 words), making it impossible to determine whether it provides substantive answers. AI answer engines need sufficient content to extract meaningful answers.',\n code: '<main>\\n <p>Provide at least 50 words of substantive content that directly answers user questions.</p>\\n</main>',\n },\n checkPage.url,\n );\n }\n }\n\n return this.pass(\n 'No excessive click-through teasers found.',\n 'No \"click to read more\" or \"contact us to learn\" teasers dominating the page',\n 'Content is self-contained',\n page.url,\n );\n }\n\n const details = teaserPages.map((tp) => `${tp.url}: ${tp.teasers.join(', ')}`).join('; ');\n\n return this.fail(\n `Found click-through teasers on ${teaserPages.length} page(s).`,\n 'No \"click to read more\" or \"contact us to learn\" teasers dominating the page',\n details.length > 200 ? details.slice(0, 200) + '...' : details,\n {\n priority: 'high',\n description:\n 'AI answer engines skip pages dominated by teaser content (\"click to read more\", \"contact us to learn\"). These pages provide no extractable answers, so agents will never surface your content in AI-generated responses. Provide substantive answers directly on the page.',\n code: '<!-- Replace \"Download our guide to learn more\" with: -->\\n<h2>How It Works</h2>\\n<p>Direct, substantive answer that AI agents can extract and cite.</p>',\n },\n teaserPages[0].url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext, PageContext } from '../../check-context';\nimport { getMainContentText } from '../../parser';\nimport { isArticleContentPage } from './dates-on-content';\n\n// Kept identical to dates-on-content / publication-date. See the comment there.\nconst DATE_PATTERN =\n /\\b(?:\\d{4}[/-]\\d{1,2}[/-]\\d{1,2}(?:[T ]\\d{2}:\\d{2}(?::\\d{2})?(?:\\.\\d+)?Z?)?|\\d{1,2}[/-]\\d{1,2}[/-]\\d{2,4}|(?:January|February|March|April|May|June|July|August|September|October|November|December|Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sept?|Oct|Nov|Dec)\\s+\\d{1,2},?\\s+\\d{4}|\\d{1,2}\\s+(?:January|February|March|April|May|June|July|August|September|October|November|December|Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sept?|Oct|Nov|Dec)\\s+\\d{4}|(?:January|February|March|April|May|June|July|August|September|October|November|December|Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sept?|Oct|Nov|Dec)\\s+\\d{4}|\\d+\\s+(?:day|week|month|year)s?\\s+ago)\\b/i;\n\nconst UPDATED_PATTERN = /\\b(?:last\\s+)?(?:updated|modified|revised)\\b/gi;\n\nexport class LastUpdatedIndicatorAudit extends Audit {\n static override meta: AuditMeta = {\n id: '9.10',\n category: 'answer-engine',\n title: 'Visible \"Last updated\" indicator',\n failureTitle: 'Visible \"Last updated\" indicator',\n description:\n 'AI engines use freshness signals like \"Last updated\" dates to rank answers. Content without freshness indicators is deprioritized for time-sensitive queries.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n applicablePageTypes: ['content'],\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'AI answer engines use \"Last updated\" indicators as freshness signals when ranking competing answers. Content without freshness indicators is deprioritized for time-sensitive queries, meaning your content may rank below older but dated content from competitors.',\n fix: 'Add a visible \"Last updated\" or \"Modified\" indicator with a machine-readable <time> element near the top of your content. Update the date whenever you revise the page.',\n code: '<p>Last updated: <time datetime=\"2025-01-15\">January 15, 2025</time></p>',\n effort: 'trivial',\n tags: ['freshness', 'html', 'answer-engine'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const contentPages = ctx.pages.filter(isArticleContentPage);\n if (contentPages.length === 0) {\n return this.notApplicable(\n 'No article content pages were scanned, so freshness indicators do not apply.',\n 'Text containing \"updated\", \"modified\", or \"revised\" adjacent to a date',\n 'No content pages',\n );\n }\n\n let keywordOnlyPage: { url: string; snippet: string } | null = null;\n\n for (const p of contentPages) {\n // (a) DOM signal: an update keyword sitting next to a <time> element.\n const domHit = this.timeWithUpdateKeyword(p);\n if (domHit) {\n return this.pass(\n 'Found a \"last updated\" indicator next to a <time> element.',\n 'Text containing \"updated\", \"modified\", or \"revised\" adjacent to a date',\n domHit.slice(0, 100),\n p.url,\n );\n }\n\n // (b) Text signal: an update keyword with a *parsed* date adjacent to it.\n const text = getMainContentText(p.$);\n UPDATED_PATTERN.lastIndex = 0;\n let m: RegExpExecArray | null;\n while ((m = UPDATED_PATTERN.exec(text)) !== null) {\n const idx = m.index;\n const window = text.slice(\n Math.max(0, idx - 24),\n Math.min(text.length, idx + m[0].length + 48),\n );\n // Require a real, parseable date (or relative phrase) — NOT just any\n // nearby 4 digits, which used to match phone numbers, SKUs and prices.\n if (DATE_PATTERN.test(window)) {\n return this.pass(\n 'Found a \"last updated\" indicator with an adjacent date.',\n 'Text containing \"updated\", \"modified\", or \"revised\" adjacent to a date',\n /* v8 ignore next -- window is bounded to ~85 chars (24 + match + 48); > 100 is unreachable */\n window.trim().length > 100 ? window.trim().slice(0, 100) + '...' : window.trim(),\n p.url,\n );\n }\n if (!keywordOnlyPage) {\n keywordOnlyPage = { url: p.url, snippet: window.trim().slice(0, 100) };\n }\n }\n }\n\n if (keywordOnlyPage) {\n return this.warn(\n 'Found \"updated\"/\"modified\" text but no clear date adjacent to it.',\n 'Text containing \"updated\", \"modified\", or \"revised\" adjacent to a date',\n keywordOnlyPage.snippet,\n {\n priority: 'medium',\n description:\n 'AI engines use the date near \"last updated\" text as a freshness signal for ranking answers. Without a machine-parseable date alongside the update indicator, agents cannot determine how current your content is, negating the freshness benefit.',\n code: '<p>Last updated: <time datetime=\"2025-01-15\">January 15, 2025</time></p>',\n },\n keywordOnlyPage.url,\n );\n }\n\n return this.fail(\n 'No \"last updated\" indicator found on any scanned content page.',\n 'Text containing \"updated\", \"modified\", or \"revised\" adjacent to a date',\n 'Not found',\n {\n priority: 'medium',\n description:\n 'AI answer engines use \"Last updated\" indicators as freshness signals when ranking competing answers. Content without freshness indicators is deprioritized for time-sensitive queries, meaning newer but unmarked content may rank below older dated content from competitors.',\n code: '<p>Last updated: <time datetime=\"2025-01-15\">January 15, 2025</time></p>',\n },\n contentPages[0].url,\n );\n }\n\n /** Returns the surrounding text if a <time> element sits next to an update keyword. */\n private timeWithUpdateKeyword(p: PageContext): string | null {\n let hit: string | null = null;\n p.$('time').each((_, el) => {\n if (hit) return;\n const time = p.$(el);\n const context = `${time.parent().text()} ${time.text()} ${time.attr('datetime') ?? ''}`;\n UPDATED_PATTERN.lastIndex = 0;\n if (UPDATED_PATTERN.test(context)) {\n hit = context.replace(/\\s+/g, ' ').trim();\n }\n });\n return hit;\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nconst ACTION_RESULT_PATTERN =\n /\\b(learn|understand|get|find|compare|see|discover|build|create|use|try|start)\\b.*\\b(how|what|why|when|steps|guide|tips|ways|results|benefits|features)\\b/i;\n\n// Concrete value signals: materials, product qualities, and trust/value props\n// that make an ecommerce description specific enough to be a useful answer\n// candidate even without a how-to formula.\nconst CONCRETE_SIGNAL =\n /\\b(cotton|wool|merino|silk|cashmere|linen|denim|leather|gold|silver|platinum|diamond|stainless|ceramic|bamboo|organic|recycled|sustainable|vegan|cruelty-free|handmade|hand-crafted|ethically|free\\s+shipping|money-back|guarantee|warranty|returns?|lifetime|waterproof|seamless|breathable|machine\\s+washable)\\b/i;\n\n// Pure-filler descriptions: a generic opener with nothing concrete after it.\nconst GENERIC_DOMINATES =\n /^(?:discover|explore|shop|browse|welcome\\s+to|find\\s+(?:out|your)|learn\\s+more|check\\s+out)\\b[^.]*$/i;\n\nexport class MetaDescriptionAeoAudit extends Audit {\n static override meta: AuditMeta = {\n id: '9.11',\n category: 'answer-engine',\n title: 'Meta description follows AEO formula',\n failureTitle: 'Meta description follows AEO formula',\n description:\n 'AI engines use meta descriptions as answer candidates. An action/result formula (\"Learn how to X to achieve Y\") matches more user queries than generic marketing language.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'high',\n guidance: {\n impact:\n 'AI engines use meta descriptions as answer candidates when generating responses. Generic marketing language (\"Discover our solutions\") provides no specific answer content and gets deprioritized. An action/result formula directly matches the queries AI agents are answering.',\n fix: 'Rewrite your meta description using an action/result formula: \"Learn how to [action] to [achieve result].\" Avoid generic openers like \"Welcome to\", \"Discover\", or \"Explore\".',\n code: '<meta name=\"description\" content=\"Learn how to optimize your site for AI engines to increase visibility in answer results and drive qualified traffic.\">',\n effort: 'easy',\n tags: ['copywriting', 'meta-tags', 'answer-engine'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const page = ctx.pages[0];\n if (!page) {\n return this.fail(\n 'No pages scanned.',\n 'Description is concrete and specific, not generic marketing filler',\n 'No pages scanned',\n {\n priority: 'high',\n description: MetaDescriptionAeoAudit.meta.description,\n code: '<meta name=\"description\" content=\"Learn how to optimize your site for AI engines to increase visibility in answer results and drive qualified traffic.\">',\n },\n );\n }\n\n const desc = page.meta?.['description'] ?? '';\n\n if (!desc) {\n return this.fail(\n 'No meta description found.',\n 'Description is concrete and specific, not generic marketing filler',\n 'Not found',\n {\n priority: 'high',\n description:\n 'AI engines use meta descriptions as answer candidates when generating responses. Without a meta description, agents must extract a summary from body text, which is less targeted. Use an action/result formula (\"Learn how to X to achieve Y\") to match more user queries.',\n code: '<meta name=\"description\" content=\"Learn how to optimize your site for AI agents to increase visibility in AI-generated answers.\">',\n },\n page.url,\n );\n }\n\n const hasActionResult = ACTION_RESULT_PATTERN.test(desc);\n const hasNumber = /\\d/.test(desc);\n // A capitalized word past the first one signals a named product/brand.\n const hasProperNoun = /\\S+\\s+.*\\b[A-Z][a-zA-Z]{2,}/.test(desc);\n const isConcrete =\n hasActionResult || hasNumber || hasProperNoun || CONCRETE_SIGNAL.test(desc);\n\n if (isConcrete) {\n return this.pass(\n hasActionResult\n ? 'Meta description follows an action/result pattern.'\n : 'Meta description is concrete and specific (named products, materials, or value props).',\n 'Description is concrete and specific, not generic marketing filler',\n desc,\n page.url,\n );\n }\n\n // Only flag when the description is dominated by generic marketing filler.\n if (GENERIC_DOMINATES.test(desc)) {\n return this.warn(\n 'Meta description is generic marketing filler with no specific answer content.',\n 'Description is concrete and specific, not generic marketing filler',\n desc,\n {\n priority: 'medium',\n description:\n 'AI engines deprioritize generic marketing language (\"Discover our solutions\") because it provides no specific answer content. Add specifics — named products, materials, numbers, or a clear value proposition — so the description can serve as an answer candidate.',\n code: '<meta name=\"description\" content=\"Learn how to optimize your site for AI engines to increase visibility in answer results and drive qualified traffic.\">',\n },\n page.url,\n );\n }\n\n // Non-empty but neither strongly concrete nor pure filler — informational,\n // not a problem worth penalizing.\n return this.pass(\n 'Meta description is present and substantive.',\n 'Description is concrete and specific, not generic marketing filler',\n desc,\n page.url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\n/** Coerce an unknown JSON value to a string; non-strings → ''. */\nfunction asString(val: unknown): string {\n return typeof val === 'string' ? val : '';\n}\n\n/**\n * Walk all JSON-LD blocks (including @graph arrays) and return every\n * object whose @type matches at least one of the given types.\n */\nfunction findJsonLdByType(jsonLd: object[], types: string[]): Record<string, unknown>[] {\n const results: Record<string, unknown>[] = [];\n const lowerTypes = new Set(types.map((t) => t.toLowerCase()));\n\n function walk(obj: unknown): void {\n if (!obj || typeof obj !== 'object') return;\n\n if (Array.isArray(obj)) {\n for (const item of obj) walk(item);\n return;\n }\n\n const record = obj as Record<string, unknown>;\n\n const objType = record['@type'];\n if (objType) {\n const typeArr = Array.isArray(objType) ? objType : [objType];\n for (const t of typeArr) {\n if (typeof t === 'string' && lowerTypes.has(t.toLowerCase())) {\n results.push(record);\n }\n }\n }\n\n // Recurse into @graph\n if (record['@graph'] && Array.isArray(record['@graph'])) {\n for (const item of record['@graph']) walk(item);\n }\n }\n\n for (const block of jsonLd) walk(block);\n return results;\n}\n\nconst GENERIC_AUTHOR_NAMES = new Set([\n 'staff',\n 'admin',\n 'administrator',\n 'team',\n 'editor',\n 'guest',\n 'contributor',\n 'unknown',\n 'author',\n 'webmaster',\n]);\n\nexport class NamedAuthorAudit extends Audit {\n static override meta: AuditMeta = {\n id: '10.1',\n category: 'generative-engine',\n title: 'Named author attribution',\n failureTitle: 'Named author attribution',\n description:\n 'AI systems assign higher confidence to content from named experts. Generic authors like \"Staff\" or \"Admin\" reduce trust scoring because agents cannot verify expertise.',\n scoreDisplayMode: 'binary',\n weight: 1.0,\n applicablePageTypes: ['content'],\n defaultPriority: 'high',\n guidance: {\n impact:\n 'AI systems assign higher confidence to content from named experts. Generic authors like \"Staff\" or \"Admin\" reduce trust scoring because agents cannot verify expertise, causing your content to rank lower in AI-generated recommendations.',\n fix: 'Replace generic author names with real person names in your JSON-LD author property, meta author tag, and visible byline. Include a jobTitle for additional authority.',\n code: '\"author\": {\\n \"@type\": \"Person\",\\n \"name\": \"Jane Smith\",\\n \"jobTitle\": \"Senior Engineer\"\\n}',\n effort: 'easy',\n tags: ['trust', 'e-e-a-t', 'json-ld', 'generative-engine'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const page = ctx.pages[0];\n if (!page) {\n return this.fail(\n 'No pages scanned.',\n 'JSON-LD author or visible byline with a named person (not \"Staff\", \"Admin\", \"Team\")',\n 'No pages scanned',\n {\n priority: 'high',\n description:\n 'AI systems assign higher confidence to content from named experts. Generic authors like \"Staff\" or \"Admin\" reduce trust scoring because agents cannot verify expertise.',\n code: '\"author\": { \"@type\": \"Person\", \"name\": \"Jane Smith\" }',\n },\n );\n }\n\n // Check JSON-LD author across all pages\n for (const p of ctx.pages) {\n const articles = findJsonLdByType(p.jsonLd, [\n 'Article',\n 'BlogPosting',\n 'NewsArticle',\n 'WebPage',\n 'TechArticle',\n ]);\n\n for (const article of articles) {\n const author = article['author'] as\n | Record<string, unknown>\n | Record<string, unknown>[]\n | string\n | undefined;\n if (!author) continue;\n\n const authors = Array.isArray(author) ? author : [author];\n for (const a of authors) {\n const name =\n typeof a === 'string'\n ? a\n : typeof a === 'object' && a !== null\n ? asString((a as Record<string, unknown>)['name'])\n : '';\n const lower = name.trim().toLowerCase();\n if (lower && !GENERIC_AUTHOR_NAMES.has(lower)) {\n return this.pass(\n `Named author found in JSON-LD: \"${name.trim()}\".`,\n 'JSON-LD author or visible byline with a named person (not \"Staff\", \"Admin\", \"Team\")',\n name.trim(),\n p.url,\n );\n }\n }\n }\n }\n\n // Check meta author tag\n for (const p of ctx.pages) {\n const metaAuthor = (p.meta?.['author'] ?? '').trim();\n if (metaAuthor && !GENERIC_AUTHOR_NAMES.has(metaAuthor.toLowerCase())) {\n return this.pass(\n `Named author found in meta tag: \"${metaAuthor}\".`,\n 'JSON-LD author or visible byline with a named person (not \"Staff\", \"Admin\", \"Team\")',\n metaAuthor,\n p.url,\n );\n }\n }\n\n // Check visible byline patterns\n for (const p of ctx.pages) {\n const $ = p.$;\n const bylineEl =\n $('[class*=\"author\"]').first().text().trim() ||\n $('[class*=\"byline\"]').first().text().trim() ||\n $('[rel=\"author\"]').first().text().trim();\n if (bylineEl && !GENERIC_AUTHOR_NAMES.has(bylineEl.toLowerCase())) {\n return this.pass(\n `Named author found in visible byline: \"${bylineEl}\".`,\n 'JSON-LD author or visible byline with a named person (not \"Staff\", \"Admin\", \"Team\")',\n bylineEl,\n p.url,\n );\n }\n }\n\n return this.fail(\n 'No named author attribution found on any scanned page.',\n 'JSON-LD author or visible byline with a named person (not \"Staff\", \"Admin\", \"Team\")',\n 'Not found',\n {\n priority: 'high',\n description:\n 'AI systems assign higher confidence to content from named experts. Generic authors like \"Staff\" or \"Admin\" reduce trust scoring because agents cannot verify expertise. A named person with verifiable credentials lets AI RAG systems cross-reference the author across platforms for authority validation.',\n code: '\"author\": { \"@type\": \"Person\", \"name\": \"Jane Smith\", \"jobTitle\": \"Senior Engineer\" }',\n },\n page.url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\n/**\n * Walk all JSON-LD blocks (including @graph arrays) and return every\n * object whose @type matches at least one of the given types.\n */\nfunction findJsonLdByType(jsonLd: object[], types: string[]): Record<string, unknown>[] {\n const results: Record<string, unknown>[] = [];\n const lowerTypes = new Set(types.map((t) => t.toLowerCase()));\n\n function walk(obj: unknown): void {\n if (!obj || typeof obj !== 'object') return;\n\n if (Array.isArray(obj)) {\n for (const item of obj) walk(item);\n return;\n }\n\n const record = obj as Record<string, unknown>;\n\n const objType = record['@type'];\n if (objType) {\n const typeArr = Array.isArray(objType) ? objType : [objType];\n for (const t of typeArr) {\n if (typeof t === 'string' && lowerTypes.has(t.toLowerCase())) {\n results.push(record);\n }\n }\n }\n\n // Recurse into @graph\n if (record['@graph'] && Array.isArray(record['@graph'])) {\n for (const item of record['@graph']) walk(item);\n }\n }\n\n for (const block of jsonLd) walk(block);\n return results;\n}\n\nexport class AuthorSameAsAudit extends Audit {\n static override meta: AuditMeta = {\n id: '10.2',\n category: 'generative-engine',\n title: 'Author schema with sameAs',\n failureTitle: 'Author schema with sameAs',\n description:\n 'AI RAG systems cross-reference author identity across platforms via sameAs URLs. Without external profile links, agents cannot verify author expertise.',\n scoreDisplayMode: 'binary',\n weight: 1.0,\n applicablePageTypes: ['content'],\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'AI RAG systems cross-reference author identity across platforms via sameAs URLs to build an expertise graph. Without external profile links, agents cannot verify that your author is the same expert they see on LinkedIn, Twitter, or GitHub, reducing trust weight.',\n fix: \"Add a sameAs array to your JSON-LD author object with URLs to the author's LinkedIn, Twitter/X, GitHub, or other professional profiles.\",\n code: '\"author\": {\\n \"@type\": \"Person\",\\n \"name\": \"Jane Smith\",\\n \"sameAs\": [\\n \"https://linkedin.com/in/janesmith\",\\n \"https://twitter.com/janesmith\",\\n \"https://github.com/janesmith\"\\n ]\\n}',\n effort: 'easy',\n docsUrl: 'https://schema.org/sameAs',\n tags: ['trust', 'e-e-a-t', 'json-ld', 'generative-engine'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const page = ctx.pages[0];\n if (!page) {\n return this.fail(\n 'No pages scanned.',\n 'JSON-LD author has sameAs array with external profile URLs',\n 'No pages scanned',\n {\n priority: 'medium',\n description:\n 'AI RAG systems cross-reference author identity across platforms via sameAs URLs. Without external profile links, agents cannot verify author expertise.',\n code: '\"author\": { \"@type\": \"Person\", \"name\": \"Jane Smith\", \"sameAs\": [\"https://linkedin.com/in/janesmith\"] }',\n },\n );\n }\n\n for (const p of ctx.pages) {\n const articles = findJsonLdByType(p.jsonLd, [\n 'Article',\n 'BlogPosting',\n 'NewsArticle',\n 'WebPage',\n 'TechArticle',\n 'Person',\n ]);\n\n for (const article of articles) {\n // Check if the object itself is a Person with sameAs\n const authorObj =\n article['@type'] === 'Person'\n ? article\n : (article['author'] as Record<string, unknown> | undefined);\n\n if (!authorObj || typeof authorObj !== 'object') continue;\n\n const authors = Array.isArray(authorObj) ? authorObj : [authorObj];\n for (const a of authors) {\n if (typeof a !== 'object' || a === null) continue;\n const rec = a as Record<string, unknown>;\n const sameAs = rec['sameAs'];\n if (Array.isArray(sameAs) && sameAs.length > 0) {\n const urls = sameAs.filter(\n (s) => typeof s === 'string' && (s.startsWith('http://') || s.startsWith('https://')),\n );\n if (urls.length > 0) {\n return this.pass(\n `Author sameAs found with ${urls.length} external profile URL(s).`,\n 'JSON-LD author has sameAs array with external profile URLs',\n urls.slice(0, 3).join(', '),\n p.url,\n );\n }\n }\n // Single string sameAs\n if (\n typeof sameAs === 'string' &&\n (sameAs.startsWith('http://') || sameAs.startsWith('https://'))\n ) {\n return this.pass(\n 'Author sameAs found with an external profile URL.',\n 'JSON-LD author has sameAs array with external profile URLs',\n sameAs,\n p.url,\n );\n }\n }\n }\n }\n\n return this.fail(\n 'No author sameAs with external profile URLs found in JSON-LD.',\n 'JSON-LD author has sameAs array with external profile URLs',\n 'Not found',\n {\n priority: 'medium',\n description:\n 'AI RAG systems cross-reference author identity across platforms via sameAs URLs to build an expertise graph. Without external profile links (LinkedIn, Twitter, GitHub), agents cannot verify that \"Jane Smith\" on your site is the same expert they see on other platforms, reducing the trust weight of your content.',\n code: '\"author\": {\\n \"@type\": \"Person\",\\n \"name\": \"Jane Smith\",\\n \"sameAs\": [\\n \"https://linkedin.com/in/janesmith\",\\n \"https://twitter.com/janesmith\",\\n \"https://github.com/janesmith\"\\n ]\\n}',\n },\n page.url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\n/**\n * Walk all JSON-LD blocks (including @graph arrays) and return every\n * object whose @type matches at least one of the given types.\n */\nfunction findJsonLdByType(jsonLd: object[], types: string[]): Record<string, unknown>[] {\n const results: Record<string, unknown>[] = [];\n const lowerTypes = new Set(types.map((t) => t.toLowerCase()));\n\n function walk(obj: unknown): void {\n if (!obj || typeof obj !== 'object') return;\n\n if (Array.isArray(obj)) {\n for (const item of obj) walk(item);\n return;\n }\n\n const record = obj as Record<string, unknown>;\n\n const objType = record['@type'];\n if (objType) {\n const typeArr = Array.isArray(objType) ? objType : [objType];\n for (const t of typeArr) {\n if (typeof t === 'string' && lowerTypes.has(t.toLowerCase())) {\n results.push(record);\n }\n }\n }\n\n // Recurse into @graph\n if (record['@graph'] && Array.isArray(record['@graph'])) {\n for (const item of record['@graph']) walk(item);\n }\n }\n\n for (const block of jsonLd) walk(block);\n return results;\n}\n\nexport class AuthorPageAudit extends Audit {\n static override meta: AuditMeta = {\n id: '10.3',\n category: 'generative-engine',\n title: 'Author page exists',\n failureTitle: 'Author page exists',\n description:\n 'AI engines follow author page links to verify credentials and build author expertise profiles. A dedicated author page strengthens E-E-A-T signals.',\n scoreDisplayMode: 'binary',\n weight: 1.0,\n applicablePageTypes: ['content'],\n defaultPriority: 'medium',\n guidance: {\n impact:\n \"AI engines follow author page URLs from JSON-LD and visible bylines to verify credentials and build expertise profiles. Without a linked, accessible author page, agents cannot validate your content creators' qualifications, reducing trust weight in AI recommendations.\",\n fix: 'Create a dedicated author page for each content creator with a bio, credentials, and expertise areas. Link to it from the JSON-LD author.url property and ensure it returns HTTP 200.',\n code: '\"author\": {\\n \"@type\": \"Person\",\\n \"name\": \"Jane Smith\",\\n \"url\": \"https://yoursite.com/authors/jane-smith\"\\n}',\n effort: 'moderate',\n tags: ['trust', 'e-e-a-t', 'json-ld', 'generative-engine'],\n },\n };\n\n async audit(ctx: CheckContext): Promise<AuditResult> {\n const page = ctx.pages[0];\n if (!page) {\n return this.fail(\n 'No pages scanned.',\n 'Author links in content resolve to 200',\n 'No pages scanned',\n {\n priority: 'medium',\n description:\n 'AI engines follow author page links to verify credentials and build author expertise profiles. A dedicated author page strengthens E-E-A-T signals.',\n code: '\"author\": { \"@type\": \"Person\", \"name\": \"Jane Smith\", \"url\": \"https://yoursite.com/authors/jane-smith\" }',\n },\n );\n }\n\n // Find author links from JSON-LD\n const authorUrls: string[] = [];\n\n for (const p of ctx.pages) {\n const articles = findJsonLdByType(p.jsonLd, [\n 'Article',\n 'BlogPosting',\n 'NewsArticle',\n 'WebPage',\n 'TechArticle',\n ]);\n for (const article of articles) {\n const author = article['author'] as\n | Record<string, unknown>\n | Record<string, unknown>[]\n | undefined;\n if (!author) continue;\n const authors = Array.isArray(author) ? author : [author];\n for (const a of authors) {\n if (typeof a === 'object' && a !== null) {\n const url = (a as Record<string, unknown>)['url'];\n if (typeof url === 'string' && url.startsWith('http')) {\n authorUrls.push(url);\n }\n }\n }\n }\n\n // Also check for author links in HTML\n const $ = p.$;\n $('a[rel=\"author\"], [class*=\"author\"] a').each((_, el) => {\n const href = $(el).attr('href');\n if (href) {\n try {\n const resolved = new URL(href, p.url).href;\n authorUrls.push(resolved);\n } catch {\n // ignore invalid URLs\n }\n }\n });\n }\n\n if (authorUrls.length === 0) {\n return this.fail(\n 'No author page links found in content or JSON-LD.',\n 'Author links in content resolve to 200',\n 'No author URLs found',\n {\n priority: 'medium',\n description:\n \"AI engines follow author page URLs from JSON-LD and visible bylines to verify credentials and build expertise profiles. Without a linked author page, agents cannot validate your content creators' qualifications, reducing trust weight in AI-generated recommendations.\",\n code: '\"author\": {\\n \"@type\": \"Person\",\\n \"name\": \"Jane Smith\",\\n \"url\": \"https://yoursite.com/authors/jane-smith\"\\n}',\n },\n page.url,\n );\n }\n\n // Verify the first author URL\n const urlToCheck = authorUrls[0];\n try {\n const result = await ctx.fetch({ url: urlToCheck });\n if (result.status === 200) {\n return this.pass(\n `Author page at \"${urlToCheck}\" returns 200.`,\n 'Author links in content resolve to 200',\n `${urlToCheck} (HTTP ${result.status})`,\n page.url,\n );\n }\n\n return this.fail(\n `Author page at \"${urlToCheck}\" returned HTTP ${result.status}.`,\n 'Author links in content resolve to 200',\n `${urlToCheck} (HTTP ${result.status})`,\n {\n priority: 'medium',\n description:\n 'AI engines that follow your author page link and get a non-200 response will flag the author as unverifiable, negating the trust benefit of having named authors. Fix the URL to return a 200 status with real author bio content.',\n code: '# Verify: curl -I https://yoursite.com/authors/jane-smith\\n# Ensure the page returns 200 with author bio content',\n },\n page.url,\n );\n } catch {\n return this.fail(\n `Failed to fetch author page at \"${urlToCheck}\".`,\n 'Author links in content resolve to 200',\n `${urlToCheck} (fetch error)`,\n {\n priority: 'medium',\n description:\n 'AI engines verify author page URLs by fetching them. A failing author page URL signals broken credentials to AI trust-scoring systems. Ensure the author page URL is reachable and returns a 200 status with meaningful bio content.',\n code: '# Fix the author URL in your JSON-LD or check for server errors\\n# curl -I https://yoursite.com/authors/jane-smith',\n },\n page.url,\n );\n }\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nconst CREDENTIAL_KEYWORDS = [\n 'team',\n 'experience',\n 'expertise',\n 'credentials',\n 'background',\n 'qualified',\n 'certified',\n 'years of experience',\n 'specializ',\n 'professional',\n];\n\nexport class AboutCredentialsAudit extends Audit {\n static override meta: AuditMeta = {\n id: '10.4',\n category: 'generative-engine',\n title: 'About page with credentials',\n failureTitle: 'About page with credentials',\n description:\n \"AI engines crawl your about page to build an organizational authority profile. Without an about page containing team credentials, expertise, and experience details, agents cannot assess your organization's authority, reducing your content's trust score in AI-generated recommendations.\",\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n \"AI engines crawl your about page to build an organizational authority profile. Without credential-rich content (team bios, expertise areas, certifications), agents cannot assess your organization's authority, reducing your content's trust score in AI-generated recommendations.\",\n fix: 'Create or expand your /about/ page to include team member bios with qualifications, years of experience, expertise areas, and professional certifications. Use specific credential keywords.',\n code: '<section>\\n <h2>Our Team</h2>\\n <p>With 15+ years of experience in software engineering, our team of certified professionals specializes in AI-powered search optimization.</p>\\n</section>',\n effort: 'moderate',\n tags: ['trust', 'e-e-a-t', 'generative-engine'],\n },\n };\n\n async audit(ctx: CheckContext): Promise<AuditResult> {\n const aboutPaths = ['/about/', '/about-us/', '/about'];\n let aboutResult = ctx.rootFiles['/about/'] ?? ctx.rootFiles['/about-us/'];\n\n if (!aboutResult || aboutResult.status !== 200) {\n // Try fetching if not in rootFiles\n for (const path of aboutPaths) {\n try {\n const result = await ctx.fetch({\n url: `${ctx.baseUrl}${path}`,\n });\n if (result.status === 200 && result.body) {\n aboutResult = result;\n break;\n }\n } catch {\n // continue trying other paths\n }\n }\n }\n\n if (!aboutResult || aboutResult.status !== 200 || !aboutResult.body) {\n return this.fail(\n 'No about page found at /about/ or /about-us/.',\n 'About page returns 200 with content mentioning \"team\", \"experience\", \"expertise\"',\n 'About page not found',\n {\n priority: 'medium',\n description:\n \"AI engines crawl your about page to build an organizational authority profile. Without an about page containing team credentials, expertise, and experience details, agents cannot assess your organization's authority, reducing your content's trust score in AI-generated recommendations.\",\n code: '<!-- Create /about/ with sections for:\\n - Company mission and history\\n - Team member bios with qualifications\\n - Years of experience and expertise areas\\n - Certifications and awards -->',\n },\n );\n }\n\n const bodyLower = aboutResult.body.toLowerCase();\n const foundKeywords = CREDENTIAL_KEYWORDS.filter((kw) => bodyLower.includes(kw));\n\n if (foundKeywords.length >= 2) {\n return this.pass(\n `About page found with credential signals: ${foundKeywords.join(', ')}.`,\n 'About page returns 200 with content mentioning \"team\", \"experience\", \"expertise\"',\n `Keywords: ${foundKeywords.join(', ')}`,\n );\n }\n\n if (foundKeywords.length === 1) {\n return this.warn(\n `About page found but has limited credential signals (only \"${foundKeywords[0]}\").`,\n 'About page returns 200 with content mentioning \"team\", \"experience\", \"expertise\"',\n `Keywords: ${foundKeywords[0]}`,\n {\n priority: 'medium',\n description:\n 'AI engines scan about pages for credential keywords (team, experience, expertise, certified) to build authority profiles. A single keyword provides weak signal. Expand to include team backgrounds, years of experience, expertise areas, and certifications for stronger AI trust scoring.',\n code: '<!-- Add sections covering:\\n - \"Our team has 15+ years of experience in...\"\\n - \"Certified by...\" or \"Qualified in...\"\\n - Specific expertise areas and specializations -->',\n },\n );\n }\n\n return this.warn(\n 'About page exists but lacks credential keywords (team, experience, expertise).',\n 'About page returns 200 with content mentioning \"team\", \"experience\", \"expertise\"',\n 'No credential keywords found',\n {\n priority: 'medium',\n description:\n 'AI engines scan about pages for credential keywords to build authority profiles but found none on yours. Add credential-rich content: team backgrounds with named experts, years of industry experience, expertise areas, and professional certifications. These signals directly influence AI trust scoring.',\n code: '<!-- Add credential-rich content like:\\n - \"Our team of 20+ engineers specializes in...\"\\n - \"With 10 years of experience in...\"\\n - \"Certified professionals in...\" -->',\n },\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class ExternalCitationsAudit extends Audit {\n static override meta: AuditMeta = {\n id: '10.5',\n category: 'generative-engine',\n title: 'External citations',\n failureTitle: 'External citations',\n description:\n 'Linking to authoritative sources signals expertise. AI RAG systems cross-reference your citations to validate claims and assess content quality.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n applicablePageTypes: ['content'],\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'AI RAG systems cross-reference your outbound citations against their knowledge graph to validate claims. Pages without external references appear as unsourced opinion, receiving lower trust scores in AI-generated answers.',\n fix: 'Add at least 2 outbound links per content page to authoritative external sources that support your claims. Link to research papers, official documentation, or industry authorities.',\n code: '<p>According to <a href=\"https://research.google/pubs/\">Google Research</a>, this approach improves accuracy by 40%.\\nSee also <a href=\"https://w3.org/standards\">W3C standards</a>.</p>',\n effort: 'easy',\n tags: ['trust', 'e-e-a-t', 'content-quality', 'generative-engine'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const page = ctx.pages[0];\n if (!page) {\n return this.fail(\n 'No pages scanned.',\n 'At least 2 <a> tags pointing to external domains per content page',\n 'No pages scanned',\n {\n priority: 'medium',\n description:\n 'Linking to authoritative sources signals expertise. AI RAG systems cross-reference your citations to validate claims and assess content quality.',\n code: '<p>According to <a href=\"https://research.google/pubs/\">Google Research</a>, this approach improves accuracy by 40%.</p>',\n },\n );\n }\n\n let pagesWithSufficientLinks = 0;\n let totalExternalLinks = 0;\n const examples: string[] = [];\n\n for (const p of ctx.pages) {\n const $ = p.$;\n const externalLinks: string[] = [];\n\n $('a[href]').each((_, el) => {\n const href = $(el).attr('href');\n if (!href) return;\n try {\n const url = new URL(href, p.url);\n if (\n url.hostname !== ctx.domain &&\n !url.hostname.endsWith(`.${ctx.domain}`) &&\n (url.protocol === 'http:' || url.protocol === 'https:')\n ) {\n externalLinks.push(url.hostname);\n }\n } catch {\n // ignore invalid URLs\n }\n });\n\n totalExternalLinks += externalLinks.length;\n if (externalLinks.length >= 2) {\n pagesWithSufficientLinks++;\n }\n if (examples.length < 5) {\n examples.push(...externalLinks.slice(0, 5 - examples.length));\n }\n }\n\n if (pagesWithSufficientLinks > 0) {\n return this.pass(\n `Found ${totalExternalLinks} external link(s) across ${ctx.pages.length} page(s); ${pagesWithSufficientLinks} page(s) have 2+ external links.`,\n 'At least 2 <a> tags pointing to external domains per content page',\n `External domains: ${[...new Set(examples)].join(', ')}`,\n page.url,\n );\n }\n\n if (totalExternalLinks > 0) {\n return this.warn(\n `Found ${totalExternalLinks} external link(s) but no page has 2+ external citations.`,\n 'At least 2 <a> tags pointing to external domains per content page',\n `External domains: ${[...new Set(examples)].join(', ')}`,\n {\n priority: 'medium',\n description:\n 'Linking to authoritative sources signals expertise to AI systems. AI RAG systems cross-reference your outbound citations against their knowledge graph to validate claims. Pages with more external citations to authoritative domains receive higher trust scores in AI-generated recommendations.',\n code: '<p>According to <a href=\"https://authoritative-source.com/study\">this research</a>, the approach improves outcomes by 40%.</p>',\n },\n page.url,\n );\n }\n\n return this.fail(\n 'No external links found on any scanned page.',\n 'At least 2 <a> tags pointing to external domains per content page',\n 'Not found',\n {\n priority: 'medium',\n description:\n 'Linking to authoritative external sources signals well-researched expertise to AI systems. AI RAG systems cross-reference citations against their knowledge graph to validate your claims. Pages without external references appear as unsourced opinion, receiving lower trust scores in AI-generated answers.',\n code: '<p>Research from <a href=\"https://authoritative-source.com\">Source</a> confirms this approach.\\nSee also <a href=\"https://another-authority.org/data\">additional data</a>.</p>',\n },\n page.url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\nimport type { CheerioAPI } from 'cheerio';\nimport { flattenJsonLd } from '../../parser';\n\n/**\n * Return every flattened JSON-LD node whose @type matches one of the given\n * types. Uses the shared deep flattener so types nested in arrays / under\n * properties (not just @graph) are found.\n */\nfunction findJsonLdByType(jsonLd: object[], types: string[]): Record<string, unknown>[] {\n const lowerTypes = new Set(types.map((t) => t.toLowerCase()));\n return (flattenJsonLd(jsonLd) as Record<string, unknown>[]).filter((record) => {\n const objType = record['@type'];\n if (!objType) return false;\n const typeArr = Array.isArray(objType) ? objType : [objType];\n return typeArr.some((t) => typeof t === 'string' && lowerTypes.has(t.toLowerCase()));\n });\n}\n\n/**\n * Full-body text (scripts/styles stripped), not just <main>. Brand mentions\n * routinely live outside <main> — header logo alt text, footer copyright\n * (\"© 2026 Acme Italy\"), nav — so a <main>-only scan false-fails brands that\n * are clearly present on the page.\n */\nfunction getBodyText($: CheerioAPI): string {\n const body = $('body').clone();\n body.find('script, style, noscript, template').remove();\n return body.text().replace(/\\s+/g, ' ').trim();\n}\n\n/**\n * Strip a trailing legal-entity suffix (\"Inc.\", \"LLC\", \"Ltd\", \"Co\", ...) so the\n * schema's legal name (\"Knix Inc.\") still matches the trading name (\"Knix\")\n * that actually appears in body copy.\n */\nfunction stripLegalSuffix(name: string): string {\n return name.replace(/[,]?\\s+(?:inc|llc|ltd|co|corp|gmbh|company)\\.?$/i, '').trim();\n}\n\nexport class BrandNameAudit extends Audit {\n static override meta: AuditMeta = {\n id: '10.6',\n category: 'generative-engine',\n title: 'Brand name in body text',\n failureTitle: 'Brand name in body text',\n description:\n 'AI engines build entity graphs by matching Organization schema names to in-content mentions. If your brand name only appears in schema but not body text, agents cannot associate your content with your entity.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'AI engines build entity graphs by matching Organization schema names to in-content mentions. If your brand name only appears in schema but not body text, agents cannot associate your content with your entity, weakening brand recognition in AI responses.',\n fix: 'Mention your brand name naturally in the body text of your pages. Ensure it matches the name in your Organization JSON-LD schema exactly.',\n code: '<p>At YourBrand, we build tools that help developers ship faster.</p>\\n\\n<!-- Ensure JSON-LD matches: -->\\n<script type=\"application/ld+json\">\\n{\"@context\":\"https://schema.org\",\"@type\":\"Organization\",\"name\":\"YourBrand\"}\\n</script>',\n effort: 'trivial',\n tags: ['brand', 'entity', 'generative-engine'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const page = ctx.pages[0];\n if (!page) {\n return this.fail(\n 'No pages scanned.',\n 'Organization name from JSON-LD appears in <main> text content',\n 'No pages scanned',\n );\n }\n\n // Collect every candidate brand name we can find. The Organization `name`\n // is often the legal entity (\"Knix Inc.\") that never appears verbatim in\n // body copy, so we also gather WebSite/publisher names and og:site_name and\n // try each (plus a legal-suffix-stripped variant) when matching.\n const candidates: string[] = [];\n const addCandidate = (value: unknown): void => {\n if (typeof value === 'string' && value.trim()) candidates.push(value.trim());\n };\n\n for (const p of ctx.pages) {\n const orgs = findJsonLdByType(p.jsonLd, ['Organization', 'LocalBusiness', 'Corporation']);\n for (const org of orgs) addCandidate(org['name']);\n\n // WebSite/Article publisher names and the WebSite's own name.\n const articles = findJsonLdByType(p.jsonLd, ['Article', 'BlogPosting', 'WebPage', 'WebSite']);\n for (const article of articles) {\n addCandidate(article['name']);\n const publisher = article['publisher'] as Record<string, unknown> | undefined;\n if (publisher && typeof publisher === 'object') addCandidate(publisher['name']);\n }\n }\n\n // Fallback: og:site_name.\n addCandidate(page.meta?.['og:site_name']);\n\n const orgName = candidates[0] ?? '';\n\n if (!orgName) {\n return this.warn(\n 'No organization name found in JSON-LD or og:site_name to check against body text.',\n 'Organization name from JSON-LD appears in <main> text content',\n 'No org name in schema',\n {\n priority: 'medium',\n description:\n 'AI agents need to identify your brand to attribute content correctly. Without an Organization schema with your brand name, agents cannot connect your pages to your entity in AI knowledge graphs. Add Organization schema and mention your brand naturally in body text.',\n code: '<script type=\"application/ld+json\">\\n{\"@context\":\"https://schema.org\",\"@type\":\"Organization\",\"name\":\"Your Brand\"}\\n</script>',\n },\n page.url,\n );\n }\n\n // Build the set of names to try: every candidate plus its\n // legal-suffix-stripped variant (de-duped, longest first so the most\n // specific brand name is reported on a match).\n const matchNames = [\n ...new Set(candidates.flatMap((c) => [c, stripLegalSuffix(c)]).filter(Boolean)),\n ].sort((a, b) => b.length - a.length);\n\n // Check if any brand name variant appears in body text of any page\n for (const p of ctx.pages) {\n const text = getBodyText(p.$);\n for (const name of matchNames) {\n const escaped = name.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n const wordBoundary = new RegExp(`\\\\b${escaped}\\\\b`, 'i');\n if (wordBoundary.test(text)) {\n return this.pass(\n `Brand name \"${name}\" appears in body text.`,\n 'Organization name from JSON-LD appears in <main> text content',\n name,\n p.url,\n );\n }\n }\n }\n\n return this.fail(\n `Brand name \"${orgName}\" not found in body text of any scanned page.`,\n 'Organization name from JSON-LD appears in <main> text content',\n `\"${orgName}\" not in body text`,\n {\n priority: 'medium',\n description:\n 'AI engines build entity graphs by matching Organization schema names to in-content mentions. If your brand name only appears in schema but not body text, agents cannot associate your content with your entity. Mention your brand name naturally in the body to strengthen entity recognition.',\n code: '<!-- Mention your brand naturally in content: -->\\n<p>At YourBrand, we build tools that help developers ship faster.</p>',\n },\n page.url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nconst TRUST_PATTERNS = [\n /trusted\\s+by/i,\n /\\bclients\\b/i,\n /\\btestimonial/i,\n /\\bcase\\s+stud/i,\n /\\baward/i,\n /\\bas\\s+seen\\s+(in|on)\\b/i,\n /\\bpartner(s|ed|ship)?\\b/i,\n /\\bcertif(ied|icate|ication)\\b/i,\n];\n\nexport class TrustSignalsAudit extends Audit {\n static override meta: AuditMeta = {\n id: '10.7',\n category: 'generative-engine',\n title: 'Trust signals on homepage',\n failureTitle: 'Trust signals on homepage',\n description:\n 'AI engines scan homepages for trust signals (client logos, testimonials, awards) as authority indicators when deciding whether to recommend your content.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'AI generative engines scan homepages for trust signals (client logos, testimonials, awards, certifications) as authority indicators when deciding whether to recommend your site. Without these signals, agents rank your site lower than competitors with visible social proof.',\n fix: 'Add a combination of trust elements to your homepage: \"Trusted by X clients\" text, a client logo grid, customer testimonials with attribution, and links to case studies or awards.',\n code: '<section>\\n <h2>Trusted by 500+ companies</h2>\\n <div class=\"client-logos\"><!-- client logo images --></div>\\n <blockquote>\\n <p>\"Outstanding results\"</p>\\n <footer>- <cite>Jane Smith, CEO at Company</cite></footer>\\n </blockquote>\\n</section>',\n effort: 'moderate',\n tags: ['trust', 'social-proof', 'generative-engine'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const page = ctx.pages[0];\n if (!page) {\n return this.fail(\n 'No pages scanned.',\n 'Homepage contains trust signals: \"trusted by\", \"clients\", \"testimonial\", \"case study\", \"award\", or logo grids',\n 'No pages scanned',\n {\n priority: 'medium',\n description:\n 'AI engines scan homepages for trust signals (client logos, testimonials, awards) as authority indicators when deciding whether to recommend your content.',\n code: '<section>\\n <h2>Trusted by 500+ companies</h2>\\n <div class=\"client-logos\"><!-- logo images --></div>\\n</section>',\n },\n );\n }\n\n const $ = page.$;\n // Scan the whole <body>, not just <main>: trust badges, \"as seen in\"\n // strips, certifications and testimonials commonly live in the footer or\n // other regions outside <main> (e.g. allbirds), and a main-scoped read\n // misses them. Clone + strip non-content nodes so inline JS/CSS in\n // <script>/<style> can't pollute the text regexes.\n const body = $('body').clone();\n body.find('script, style, noscript, template').remove();\n const text = body.text().replace(/\\s+/g, ' ').trim();\n const foundSignals: string[] = [];\n\n for (const pattern of TRUST_PATTERNS) {\n const match = text.match(pattern);\n if (match) {\n foundSignals.push(match[0]);\n }\n }\n\n // Check for image grids (common logo carousel/grid patterns)\n const logoGrids = $('[class*=\"logo\"], [class*=\"client\"], [class*=\"partner\"], [class*=\"trust\"]');\n const imgInGrids = logoGrids.find('img').length;\n if (imgInGrids >= 3) {\n foundSignals.push(`image grid (${imgInGrids} logos)`);\n }\n\n if (foundSignals.length >= 2) {\n return this.pass(\n `Found ${foundSignals.length} trust signal(s) on homepage.`,\n 'Homepage contains trust signals: \"trusted by\", \"clients\", \"testimonial\", \"case study\", \"award\", or logo grids',\n foundSignals.join(', '),\n page.url,\n );\n }\n\n if (foundSignals.length === 1) {\n return this.warn(\n `Only 1 trust signal found: \"${foundSignals[0]}\".`,\n 'Homepage contains trust signals: \"trusted by\", \"clients\", \"testimonial\", \"case study\", \"award\", or logo grids',\n foundSignals[0],\n {\n priority: 'medium',\n description:\n 'AI engines scan homepages for trust signals as authority indicators when deciding whether to recommend your content. A single trust signal is weak. Add a combination of \"Trusted by X clients\" text, client logo grids, testimonials, and case study links to build a stronger authority profile.',\n code: '<section>\\n <h2>Trusted by 500+ companies</h2>\\n <div class=\"client-logos\"><!-- logo images --></div>\\n</section>\\n<section>\\n <h2>What our clients say</h2>\\n <blockquote><p>\"Excellent service\"</p><footer>- Client Name</footer></blockquote>\\n</section>',\n },\n page.url,\n );\n }\n\n return this.fail(\n 'No trust signals found on the homepage.',\n 'Homepage contains trust signals: \"trusted by\", \"clients\", \"testimonial\", \"case study\", \"award\", or logo grids',\n 'Not found',\n {\n priority: 'medium',\n description:\n 'AI generative engines scan homepages for trust signals when assessing whether to recommend your site in AI-generated answers. Without trust indicators like client counts, testimonials, case studies, or awards, agents rank your site lower than competitors with visible social proof.',\n code: '<section>\\n <h2>Trusted by 500+ companies</h2>\\n <div class=\"client-logos\"><!-- client logo images --></div>\\n <blockquote>\\n <p>\"Outstanding results\"</p>\\n <footer>- <cite>Jane Smith, CEO at Company</cite></footer>\\n </blockquote>\\n</section>',\n },\n page.url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\nimport { flattenJsonLd } from '../../parser';\n\n/**\n * Scan deeply-flattened JSON-LD nodes for review evidence. Real Shopify themes\n * nest `aggregateRating`/`review` inside Product nodes (not just inside\n * @graph), so we rely on the shared `flattenJsonLd` deep recursion and then\n * match on both the @type and the property keys that carry review data.\n */\nfunction findReviewNodes(jsonLd: object[]): string[] {\n const found: string[] = [];\n const nodes = flattenJsonLd(jsonLd) as Record<string, unknown>[];\n\n for (const record of nodes) {\n const objType = record['@type'];\n if (objType) {\n const typeArr = Array.isArray(objType) ? objType : [objType];\n for (const t of typeArr) {\n if (typeof t === 'string' && /^(?:aggregaterating|review)$/i.test(t)) {\n found.push(t);\n }\n }\n }\n\n // Nested review properties carried on a parent node (e.g. a Product with\n // `aggregateRating`/`review`/`reviewCount` but no dedicated Review node).\n if (record['aggregateRating']) found.push('aggregateRating');\n if (record['review']) found.push('review');\n if (record['reviewCount'] || record['ratingCount']) found.push('reviewCount');\n }\n\n return [...new Set(found)];\n}\n\nexport class ReviewSignalsAudit extends Audit {\n static override meta: AuditMeta = {\n id: '10.8',\n category: 'generative-engine',\n title: 'Review/testimonial signals',\n failureTitle: 'Review/testimonial signals',\n description:\n 'AI engines use reviews and testimonials as social proof signals when recommending products or services in generated answers.',\n scoreDisplayMode: 'binary',\n weight: 1.0,\n applicablePageTypes: ['homepage', 'product'],\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'AI generative engines use reviews and testimonials as social proof when recommending your product or service. Without machine-readable review signals, agents have no evidence to cite when users ask \"is this product any good?\".',\n fix: 'Add Review or AggregateRating JSON-LD schema, or use attributed <blockquote> elements with <cite> and <footer> for testimonials on your homepage and product pages.',\n code: '<blockquote cite=\"https://example.com/review\">\\n <p>\"Great product -- reduced our deployment time by 50%.\"</p>\\n <footer>- <cite>Jane Smith, CEO at Company</cite></footer>\\n</blockquote>',\n effort: 'moderate',\n docsUrl: 'https://schema.org/Review',\n tags: ['trust', 'social-proof', 'schema', 'generative-engine'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const page = ctx.pages[0];\n if (!page) {\n return this.fail(\n 'No pages scanned.',\n 'JSON-LD Review/AggregateRating or <blockquote> elements with attribution',\n 'No pages scanned',\n {\n priority: 'medium',\n description:\n 'AI engines use reviews and testimonials as social proof signals when recommending products or services in generated answers.',\n code: '<blockquote>\\n <p>\"Great product!\"</p>\\n <footer>- <cite>Jane Smith, CEO</cite></footer>\\n</blockquote>',\n },\n );\n }\n\n const signals: string[] = [];\n\n for (const p of ctx.pages) {\n // Check JSON-LD for reviews (deep-flattened: catches nested\n // aggregateRating/review on Product nodes, not just @graph entries).\n const reviewNodes = findReviewNodes(p.jsonLd);\n if (reviewNodes.length > 0) {\n signals.push(`JSON-LD ${reviewNodes.join(', ')}`);\n }\n\n // Check for blockquotes with attribution (cite attr or <cite> child)\n const $ = p.$;\n const blockquotes = $('blockquote');\n if (blockquotes.length > 0) {\n let withAttribution = 0;\n blockquotes.each((_, el) => {\n const hasCite =\n $(el).attr('cite') || $(el).find('cite').length > 0 || $(el).find('footer').length > 0;\n if (hasCite) withAttribution++;\n });\n\n if (withAttribution > 0) {\n signals.push(`${withAttribution} attributed blockquote(s)`);\n } else {\n signals.push(`${blockquotes.length} blockquote(s) (no attribution)`);\n }\n }\n\n // DOM fallback: many stores render reviews via third-party widgets\n // (Yotpo, Okendo, Judge.me, Loox, Stamped...) whose schema is injected\n // client-side and so is absent from the server HTML JSON-LD. Detect the\n // widget markup or visible \"N reviews\" copy before failing.\n if (signals.length === 0) {\n const widget = $(\n '[class*=\"yotpo\"],[class*=\"okendo\"],[class*=\"jdgm\"],[class*=\"judgeme\"],[class*=\"loox\"],[class*=\"stamped\"],[class*=\"star-rating\"]',\n );\n if (widget.length > 0) {\n signals.push('review widget markup');\n } else if (/\\b\\d[\\d,]*\\s+reviews?\\b/i.test($('body').text())) {\n signals.push('\"N reviews\" text');\n }\n }\n }\n\n if (signals.length > 0) {\n return this.pass(\n `Review/testimonial signals found: ${signals.join('; ')}.`,\n 'JSON-LD Review/AggregateRating or <blockquote> elements with attribution',\n signals.join('; '),\n page.url,\n );\n }\n\n return this.fail(\n 'No review or testimonial signals found.',\n 'JSON-LD Review/AggregateRating or <blockquote> elements with attribution',\n 'Not found',\n {\n priority: 'medium',\n description:\n 'AI generative engines use reviews and testimonials as social proof when recommending your product or service. Attributed blockquotes and Review/AggregateRating schema make social proof machine-readable, giving agents concrete evidence to cite when users ask \"is X any good?\".',\n code: '<blockquote cite=\"https://example.com/review\">\\n <p>\"Great product — reduced our deployment time by 50%.\"</p>\\n <footer>- <cite>Jane Smith, CEO at Company</cite></footer>\\n</blockquote>',\n },\n page.url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext, PageContext } from '../../check-context';\nimport { getMainContentText, flattenJsonLd } from '../../parser';\n\n// Kept identical to dates-on-content / last-updated. See the comment there.\nconst DATE_PATTERN =\n /\\b(?:\\d{4}[/-]\\d{1,2}[/-]\\d{1,2}(?:[T ]\\d{2}:\\d{2}(?::\\d{2})?(?:\\.\\d+)?Z?)?|\\d{1,2}[/-]\\d{1,2}[/-]\\d{2,4}|(?:January|February|March|April|May|June|July|August|September|October|November|December|Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sept?|Oct|Nov|Dec)\\s+\\d{1,2},?\\s+\\d{4}|\\d{1,2}\\s+(?:January|February|March|April|May|June|July|August|September|October|November|December|Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sept?|Oct|Nov|Dec)\\s+\\d{4}|(?:January|February|March|April|May|June|July|August|September|October|November|December|Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sept?|Oct|Nov|Dec)\\s+\\d{4}|\\d+\\s+(?:day|week|month|year)s?\\s+ago)\\b/i;\n\n/** Gate to genuine article pages — excludes XML sitemaps and interstitials. */\nfunction isArticleContentPage(p: PageContext): boolean {\n if (p.pageType !== 'content') return false;\n let pathname = '';\n try {\n pathname = new URL(p.url).pathname.toLowerCase();\n } catch {\n pathname = '';\n }\n if (pathname.endsWith('.xml')) return false;\n /* v8 ignore next -- fetchResult.body is always a string in all callers; the ?? '' is a safety guard */\n const head = (p.fetchResult.body ?? '').slice(0, 256).trimStart().toLowerCase();\n if (head.startsWith('<?xml') || head.startsWith('<urlset') || head.startsWith('<sitemapindex')) {\n return false;\n }\n return true;\n}\n\nfunction findJsonLdDate(jsonLd: object[]): string | null {\n for (const node of flattenJsonLd(jsonLd)) {\n const n = node as Record<string, unknown>;\n const v = n['datePublished'] ?? n['dateModified'] ?? n['uploadDate'] ?? n['dateCreated'];\n if (typeof v === 'string' && v.trim()) return v.trim();\n }\n return null;\n}\n\nfunction findStructuredDate(p: PageContext): { value: string; source: string } | null {\n const timeWithAttr = p.$('time[datetime]').first();\n if (timeWithAttr.length) {\n /* v8 ignore next -- time[datetime] selector guarantees the attribute exists; the ?? fallback is unreachable */\n return { value: timeWithAttr.attr('datetime') ?? timeWithAttr.text().trim(), source: '<time datetime>' };\n }\n const jsonDate = findJsonLdDate(p.structuredData ?? p.jsonLd);\n if (jsonDate) return { value: jsonDate, source: 'JSON-LD' };\n const metaDate =\n p.meta['article:published_time'] ??\n p.meta['article:modified_time'] ??\n p.meta['og:updated_time'];\n if (metaDate?.trim()) return { value: metaDate.trim(), source: 'meta' };\n const anyTime = p.$('time').first();\n if (anyTime.length) {\n const v = anyTime.attr('datetime') ?? anyTime.text().trim();\n if (v) return { value: v, source: '<time>' };\n }\n return null;\n}\n\nexport class PublicationDateAudit extends Audit {\n static override meta: AuditMeta = {\n id: '10.9',\n category: 'generative-engine',\n title: 'Publication date visible',\n failureTitle: 'Publication date visible',\n description:\n 'AI engines use visible dates to assess content freshness. Undated content is deprioritized for recency-weighted queries.',\n scoreDisplayMode: 'binary',\n weight: 1.0,\n applicablePageTypes: ['content'],\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'AI generative engines use visible publication dates as a freshness signal when ranking content sources. Undated content is deprioritized because agents cannot determine whether the information is current, especially for topics where recency matters.',\n fix: 'Add a visible publication date using the <time> element with a machine-readable datetime attribute. Place it prominently near the article title.',\n code: '<p>Published: <time datetime=\"2025-01-15\">January 15, 2025</time></p>',\n effort: 'trivial',\n tags: ['freshness', 'html', 'generative-engine'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const contentPages = ctx.pages.filter(isArticleContentPage);\n if (contentPages.length === 0) {\n return this.notApplicable(\n 'No article content pages were scanned, so publication dates do not apply.',\n '<time> element or visible date on content pages',\n 'No content pages',\n );\n }\n\n for (const p of contentPages) {\n const structured = findStructuredDate(p);\n if (structured) {\n return this.pass(\n `Found a structured date (${structured.source}).`,\n '<time> element or visible date on content pages',\n `${structured.source}: \"${structured.value}\"`,\n p.url,\n );\n }\n\n const text = getMainContentText(p.$);\n const dateMatch = text.match(DATE_PATTERN);\n if (dateMatch) {\n return this.pass(\n 'Visible date found in content.',\n '<time> element or visible date on content pages',\n dateMatch[0],\n p.url,\n );\n }\n }\n\n return this.fail(\n 'No visible publication date found on any scanned page.',\n '<time> element or visible date on content pages',\n 'Not found',\n {\n priority: 'medium',\n description:\n 'AI generative engines use visible publication dates as a freshness signal when ranking content sources. Undated content is deprioritized because agents cannot determine whether the information is current, especially for topics where recency matters like technology, regulations, or market data.',\n code: '<p>Published: <time datetime=\"2025-01-15\">January 15, 2025</time></p>',\n },\n contentPages[0].url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\n/** Coerce an unknown JSON value to a string; non-strings → ''. */\nfunction asString(val: unknown): string {\n return typeof val === 'string' ? val : '';\n}\n\n/**\n * Walk all JSON-LD blocks (including @graph arrays) and return every\n * object whose @type matches at least one of the given types.\n */\nfunction findJsonLdByType(jsonLd: object[], types: string[]): Record<string, unknown>[] {\n const results: Record<string, unknown>[] = [];\n const lowerTypes = new Set(types.map((t) => t.toLowerCase()));\n\n function walk(obj: unknown): void {\n if (!obj || typeof obj !== 'object') return;\n\n if (Array.isArray(obj)) {\n for (const item of obj) walk(item);\n return;\n }\n\n const record = obj as Record<string, unknown>;\n\n const objType = record['@type'];\n if (objType) {\n const typeArr = Array.isArray(objType) ? objType : [objType];\n for (const t of typeArr) {\n if (typeof t === 'string' && lowerTypes.has(t.toLowerCase())) {\n results.push(record);\n }\n }\n }\n\n // Recurse into @graph\n if (record['@graph'] && Array.isArray(record['@graph'])) {\n for (const item of record['@graph']) walk(item);\n }\n }\n\n for (const block of jsonLd) walk(block);\n return results;\n}\n\nexport class LastModifiedSchemaAudit extends Audit {\n static override meta: AuditMeta = {\n id: '10.10',\n category: 'generative-engine',\n title: 'Last modified date in schema',\n failureTitle: 'Last modified date in schema',\n description:\n 'AI engines use dateModified in JSON-LD to determine content freshness. Content that shows recent updates is prioritized over stale content.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n applicablePageTypes: ['content'],\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'AI generative engines use dateModified in JSON-LD to rank content by freshness. Without it, agents cannot determine when your content was last reviewed, causing it to be treated as potentially stale compared to competitors with recent dateModified values.',\n fix: 'Add a dateModified property to your Article/BlogPosting JSON-LD that differs from datePublished. Update dateModified automatically whenever you revise the content.',\n code: '{\\n \"@type\": \"Article\",\\n \"datePublished\": \"2025-01-01T10:00:00Z\",\\n \"dateModified\": \"2025-01-20T10:00:00Z\"\\n}',\n effort: 'easy',\n docsUrl: 'https://schema.org/dateModified',\n tags: ['freshness', 'json-ld', 'schema', 'generative-engine'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const page = ctx.pages[0];\n if (!page) {\n return this.fail(\n 'No pages scanned.',\n 'JSON-LD dateModified present and different from datePublished',\n 'No pages scanned',\n {\n priority: 'medium',\n description:\n 'AI engines use dateModified in JSON-LD to determine content freshness. Content that shows recent updates is prioritized over stale content.',\n code: '\"dateModified\": \"2025-01-20T10:00:00Z\"',\n },\n );\n }\n\n for (const p of ctx.pages) {\n const articles = findJsonLdByType(p.structuredData ?? p.jsonLd, [\n 'Article',\n 'BlogPosting',\n 'NewsArticle',\n 'WebPage',\n 'TechArticle',\n ]);\n\n for (const article of articles) {\n const dateModified = article['dateModified'];\n const datePublished = article['datePublished'];\n\n if (typeof dateModified === 'string' && dateModified.trim()) {\n if (typeof datePublished === 'string' && dateModified.trim() !== datePublished.trim()) {\n return this.pass(\n `dateModified (\"${dateModified}\") differs from datePublished (\"${datePublished}\").`,\n 'JSON-LD dateModified present and different from datePublished',\n `dateModified: ${dateModified}, datePublished: ${datePublished}`,\n p.url,\n );\n }\n\n // dateModified exists but same as datePublished or no datePublished\n return this.warn(\n datePublished\n ? `dateModified equals datePublished (\"${dateModified}\"). Update dateModified when content changes.`\n : `dateModified is set (\"${dateModified}\") but no datePublished for comparison.`,\n 'JSON-LD dateModified present and different from datePublished',\n `dateModified: ${dateModified}${datePublished ? `, datePublished: ${asString(datePublished)}` : ''}`,\n {\n priority: 'low',\n description:\n 'AI engines compare dateModified to datePublished to detect actively maintained content. When they match, agents treat the content as never-updated since publication. Update dateModified each time you revise content to signal freshness.',\n },\n p.url,\n );\n }\n }\n }\n\n return this.fail(\n 'No dateModified found in any JSON-LD schema.',\n 'JSON-LD dateModified present and different from datePublished',\n 'Not found',\n {\n priority: 'medium',\n description:\n 'AI generative engines use dateModified in JSON-LD to rank content by freshness. Without it, agents cannot determine when your content was last reviewed, causing it to be treated as potentially stale. Add dateModified and update it whenever you revise content.',\n code: '\"datePublished\": \"2025-01-01T10:00:00Z\",\\n\"dateModified\": \"2025-01-20T10:00:00Z\"',\n },\n page.url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\nimport { extractInternalLinks } from '../../parser';\n\nexport class InternalCrossLinkingAudit extends Audit {\n static override meta: AuditMeta = {\n id: '10.11',\n category: 'generative-engine',\n title: 'Internal cross-linking',\n failureTitle: 'Internal cross-linking',\n description:\n 'AI engines use internal link structure to understand topic relationships and site authority. Pages without internal links are treated as isolated content.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'high',\n guidance: {\n impact:\n 'AI engines use internal link structure to build topic clusters and assess site authority. Pages without internal cross-links are treated as isolated, orphaned content with no topical context, reducing their authority in AI-generated recommendations.',\n fix: \"Add at least 2 contextual internal links per page pointing to related content on your site. Use descriptive anchor text that indicates the linked page's topic.\",\n code: '<p>Related resources:\\n <a href=\"/getting-started\">Getting Started Guide</a> |\\n <a href=\"/api-reference\">API Reference</a> |\\n <a href=\"/examples\">Code Examples</a>\\n</p>',\n effort: 'easy',\n tags: ['site-structure', 'linking', 'generative-engine'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const page = ctx.pages[0];\n if (!page) {\n return this.fail(\n 'No pages scanned.',\n 'Content pages link to >=2 other internal pages',\n 'No pages scanned',\n {\n priority: 'high',\n description:\n 'AI engines use internal link structure to understand topic relationships and site authority. Pages without internal links are treated as isolated content.',\n code: '<p>Learn more about <a href=\"/related-topic\">related topic</a> and <a href=\"/another-page\">another resource</a>.</p>',\n },\n );\n }\n\n let wellLinkedPages = 0;\n let totalInternalLinks = 0;\n\n for (const p of ctx.pages) {\n const links = extractInternalLinks(p.$, ctx.domain);\n // Exclude self-links\n const otherLinks = links.filter((l) => {\n try {\n const linkUrl = new URL(l);\n const pageUrl = new URL(p.url);\n return linkUrl.pathname !== pageUrl.pathname;\n } catch {\n /* v8 ignore next */\n return true;\n }\n });\n totalInternalLinks += otherLinks.length;\n if (otherLinks.length >= 2) {\n wellLinkedPages++;\n }\n }\n\n if (wellLinkedPages === ctx.pages.length && ctx.pages.length > 0) {\n return this.pass(\n `All ${ctx.pages.length} page(s) have 2+ internal cross-links (${totalInternalLinks} total).`,\n 'Content pages link to >=2 other internal pages',\n `${totalInternalLinks} internal links across ${ctx.pages.length} page(s)`,\n page.url,\n );\n }\n\n if (wellLinkedPages > 0) {\n return this.warn(\n `${wellLinkedPages} of ${ctx.pages.length} page(s) have 2+ internal cross-links.`,\n 'Content pages link to >=2 other internal pages',\n `${wellLinkedPages}/${ctx.pages.length} pages well-linked`,\n {\n priority: 'medium',\n description:\n 'AI engines build topic clusters from internal link structure. Pages with fewer than 2 internal links appear as isolated content with weak topical authority. Add contextual links to related pages so agents can map your content hierarchy and surface related answers.',\n code: '<p>See also: <a href=\"/related-guide\">our guide to related topic</a> and <a href=\"/case-study\">this case study</a>.</p>',\n },\n page.url,\n );\n }\n\n return this.fail(\n `No scanned page has 2+ internal cross-links to other pages.`,\n 'Content pages link to >=2 other internal pages',\n `${totalInternalLinks} total internal links`,\n {\n priority: 'high',\n description:\n 'AI engines use internal link structure to build topic clusters and assess site authority. Pages without internal cross-links are treated as isolated, orphaned content with no topical context. Add at least 2 contextual links per page to related content on your site.',\n code: '<p>Related resources:\\n <a href=\"/getting-started\">Getting Started Guide</a> |\\n <a href=\"/api-reference\">API Reference</a> |\\n <a href=\"/examples\">Code Examples</a>\\n</p>',\n },\n page.url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class PaginationLinksAudit extends Audit {\n static override meta: AuditMeta = {\n id: '10.12',\n category: 'generative-engine',\n title: 'Pagination links',\n failureTitle: 'Pagination links',\n description:\n 'AI crawlers use rel=\"prev\" and rel=\"next\" to navigate paginated content series without missing pages.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n applicablePageTypes: ['category'],\n defaultPriority: 'low',\n guidance: {\n impact:\n 'AI crawlers use rel=\"prev\" and rel=\"next\" to navigate paginated content series sequentially. Without these links, agents may miss pages in a series or index paginated listings out of order, leading to incomplete content coverage in AI knowledge bases.',\n fix: 'Add <link rel=\"prev\"> and <link rel=\"next\"> tags in the <head> of paginated pages pointing to the previous and next pages in the series.',\n code: '<link rel=\"prev\" href=\"/blog/page/1\">\\n<link rel=\"next\" href=\"/blog/page/3\">',\n effort: 'easy',\n tags: ['pagination', 'html', 'generative-engine'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const page = ctx.pages[0];\n if (!page) {\n return this.fail(\n 'No pages scanned.',\n '<link rel=\"prev\"> and <link rel=\"next\"> in head',\n 'No pages scanned',\n {\n priority: 'low',\n description:\n 'AI crawlers use rel=\"prev\" and rel=\"next\" to navigate paginated content series without missing pages.',\n code: '<link rel=\"prev\" href=\"/blog/page/1\">\\n<link rel=\"next\" href=\"/blog/page/3\">',\n },\n );\n }\n\n for (const p of ctx.pages) {\n const hasPrev = p.headLinks.some((l) => l.rel === 'prev');\n const hasNext = p.headLinks.some((l) => l.rel === 'next');\n\n if (hasPrev || hasNext) {\n const found: string[] = [];\n if (hasPrev) found.push('rel=\"prev\"');\n if (hasNext) found.push('rel=\"next\"');\n\n return this.pass(\n `Pagination links found: ${found.join(' and ')}.`,\n '<link rel=\"prev\"> and <link rel=\"next\"> in head',\n found.join(', '),\n p.url,\n );\n }\n }\n\n // Pagination links are only needed on paginated content; their absence is not critical\n return this.warn(\n 'No <link rel=\"prev\"> or <link rel=\"next\"> found on any page.',\n '<link rel=\"prev\"> and <link rel=\"next\"> in head',\n 'Not found',\n {\n priority: 'low',\n description:\n 'AI crawlers use rel=\"prev\" and rel=\"next\" to navigate paginated content series sequentially. Without these links, agents may miss pages in a series or index paginated listings out of order, leading to incomplete content coverage in AI knowledge bases.',\n code: '<link rel=\"prev\" href=\"/blog/page/1\">\\n<link rel=\"next\" href=\"/blog/page/3\">',\n },\n page.url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\nimport { getMainContentText } from '../../parser';\n\n// Match only unit/currency/percent/magnitude-anchored figures. A bare\n// `\\d+\\.\\d+` matched shoe sizes, raw JS floats and phone-number fragments,\n// flooding the result with noise; requiring a %, $, thousands-separator or an\n// \"x\" multiplier keeps genuinely citable statistics.\nconst STAT_PATTERN = /\\d+(?:\\.\\d+)?%|\\$[\\d,]+(?:\\.\\d{2})?|\\b\\d{1,3}(?:,\\d{3})+\\b|\\b\\d+(?:\\.\\d+)?x\\b/;\n\nexport class UniqueDataAudit extends Audit {\n static override meta: AuditMeta = {\n id: '10.13',\n category: 'generative-engine',\n title: 'Unique data or statistics',\n failureTitle: 'Unique data or statistics',\n description:\n 'AI generative engines prioritize content with original, citable data points over vague claims. Include specific statistics and metrics.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'medium',\n guidance: {\n impact:\n 'AI generative engines prioritize content with unique, citable data points because agents can quote exact figures in generated answers. Content without specific numbers reads as opinion rather than evidence, reducing its chances of being cited.',\n fix: 'Add specific statistics, percentages, dollar amounts, and measurable metrics to your content. Include original data from surveys, benchmarks, or internal metrics where possible.',\n code: '<p>Results from our 2024 survey of 1,200 developers show that 73% prefer structured APIs, with an average integration time of 2.5 hours.</p>',\n effort: 'easy',\n tags: ['content-quality', 'data', 'generative-engine'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const page = ctx.pages[0];\n if (!page) {\n return this.fail(\n 'No pages scanned.',\n 'Content has numbers, percentages, or original data points',\n 'No pages scanned',\n {\n priority: 'medium',\n description:\n 'AI generative engines prioritize content with original, citable data points over vague claims. Include specific statistics and metrics.',\n code: '<p>Our platform handles 50,000 requests/second with 99.9% uptime.</p>',\n },\n );\n }\n\n const allMatches: string[] = [];\n\n for (const p of ctx.pages) {\n const text = getMainContentText(p.$);\n const matches = text.match(new RegExp(STAT_PATTERN.source, 'g'));\n if (matches) {\n allMatches.push(...matches.slice(0, 10));\n }\n }\n\n if (allMatches.length >= 3) {\n return this.pass(\n `Found ${allMatches.length} data points across scanned pages.`,\n 'Content has numbers, percentages, or original data points',\n `Examples: ${[...new Set(allMatches)].slice(0, 5).join(', ')}`,\n page.url,\n );\n }\n\n if (allMatches.length > 0) {\n return this.warn(\n `Only ${allMatches.length} data point(s) found. Consider adding more statistics.`,\n 'Content has numbers, percentages, or original data points',\n `Examples: ${allMatches.join(', ')}`,\n {\n priority: 'low',\n description:\n 'AI generative engines prefer content with concrete, citable data over vague claims. Adding more statistics, percentages, and specific metrics makes your content more quotable in AI-generated answers, increasing the likelihood of being cited as a source.',\n code: '<p>Our solution improves performance by 65%, reduces costs by $2,500/month, and serves 10,000+ daily users.</p>',\n },\n page.url,\n );\n }\n\n return this.fail(\n 'No numbers, percentages, or data points found in content.',\n 'Content has numbers, percentages, or original data points',\n 'Not found',\n {\n priority: 'medium',\n description:\n 'AI generative engines prioritize content with unique, citable data points because agents can quote exact figures in generated answers. Content without specific numbers reads as opinion rather than evidence, reducing its chances of being selected as a source in AI responses.',\n code: '<p>Results from our 2024 survey of 1,200 developers show that 73% prefer structured APIs over unstructured endpoints.</p>',\n },\n page.url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nexport class BlockquoteUsageAudit extends Audit {\n static override meta: AuditMeta = {\n id: '10.14',\n category: 'generative-engine',\n title: 'Blockquote/callout usage',\n failureTitle: 'Blockquote/callout usage',\n description:\n 'AI engines extract <blockquote> content as notable citations and key takeaways in generated answers.',\n scoreDisplayMode: 'binary',\n weight: 1.0,\n defaultPriority: 'low',\n guidance: {\n impact:\n 'AI generative engines extract <blockquote> content as notable citations and key takeaways when generating summaries. Blockquoted text is treated as high-signal content that deserves prominent placement in AI-generated answers.',\n fix: 'Wrap key quotes, testimonials, and important takeaways in <blockquote> elements. Add a <footer> with <cite> for proper attribution.',\n code: '<blockquote>\\n <p>\"The single most impactful change is adding structured data to your pages.\"</p>\\n <footer>- <cite>Industry Expert</cite></footer>\\n</blockquote>',\n effort: 'trivial',\n tags: ['content-structure', 'html', 'generative-engine'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const page = ctx.pages[0];\n if (!page) {\n return this.fail('No pages scanned.', '<blockquote> elements present', 'No pages scanned', {\n priority: 'low',\n description:\n 'AI engines extract <blockquote> content as notable citations and key takeaways in generated answers.',\n code: '<blockquote>\\n <p>Key insight or notable quote here.</p>\\n</blockquote>',\n });\n }\n\n let totalBlockquotes = 0;\n let pageWithBlockquote: string | undefined;\n\n for (const p of ctx.pages) {\n const count = p.$('blockquote').length;\n if (count > 0) {\n totalBlockquotes += count;\n if (!pageWithBlockquote) {\n pageWithBlockquote = p.url;\n }\n }\n }\n\n if (totalBlockquotes > 0) {\n return this.pass(\n `Found ${totalBlockquotes} <blockquote> element(s) across scanned pages.`,\n '<blockquote> elements present',\n `${totalBlockquotes} blockquote(s)`,\n pageWithBlockquote,\n );\n }\n\n return this.fail(\n 'No <blockquote> elements found on any scanned page.',\n '<blockquote> elements present',\n 'Not found',\n {\n priority: 'low',\n description:\n 'AI generative engines extract <blockquote> content as notable citations and key takeaways when generating summaries. Blockquoted text is treated as high-signal content that deserves prominent placement in AI-generated answers, making it an effective way to highlight your most important points.',\n code: '<blockquote>\\n <p>\"The single most impactful change is adding structured data to your pages.\"</p>\\n <footer>- <cite>Source attribution</cite></footer>\\n</blockquote>',\n },\n page.url,\n );\n }\n}\n","import type { AuditMeta, AuditResult } from \"../../types\";\nimport { Audit } from \"../../audit\";\nimport type { CheckContext } from '../../check-context';\n\nconst BAD_SLUG_PATTERNS = [\n /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/i, // UUID\n /\\/post-\\d+\\/?$/i, // /post-123/\n /\\/page-\\d+\\/?$/i, // /page-123/\n /\\/p\\/\\d+\\/?$/i, // /p/123/\n /\\/\\d{5,}\\/?$/i, // just a long numeric ID\n /[?&](?:id|p|page_id)=\\d+/i, // ?id=123 or ?p=123\n /%[0-9A-Fa-f]{2}.*%[0-9A-Fa-f]{2}/, // heavily encoded URLs\n /\\/[a-z]*\\/\\d+\\/?$/i, // /post/12345 or /article/789 — short word + numeric ID\n];\n\nexport class DescriptiveUrlsAudit extends Audit {\n static override meta: AuditMeta = {\n id: '10.15',\n category: 'generative-engine',\n title: 'Descriptive URL slugs',\n failureTitle: 'Descriptive URL slugs',\n description:\n 'AI engines use URL text as a content signal. Descriptive slugs help agents understand page topics before fetching the content.',\n scoreDisplayMode: 'ternary',\n weight: 1.0,\n defaultPriority: 'high',\n guidance: {\n impact:\n \"AI engines use URL text as a pre-fetch topic signal and display URLs in generated citations. Non-descriptive slugs with UUIDs or numeric IDs provide no topical context, reducing your content's relevance score before the page is even crawled.\",\n fix: 'Replace non-descriptive URL slugs (UUIDs, numeric IDs, encoded params) with keyword-rich, human-readable paths that describe the page content.',\n code: '<!-- Change:\\n /post-123/ -> /how-to-optimize-for-ai/\\n /p/456/ -> /pricing-comparison/\\n /?id=789 -> /getting-started-guide/\\n /article/abc-def -> /ai-search-best-practices/ -->',\n effort: 'moderate',\n tags: ['url-structure', 'seo', 'generative-engine'],\n },\n };\n\n audit(ctx: CheckContext): AuditResult {\n const page = ctx.pages[0];\n if (!page) {\n return this.fail(\n 'No pages scanned.',\n 'Page URLs use readable slugs (no UUIDs, no /post-123/, no encoded params)',\n 'No pages scanned',\n {\n priority: 'high',\n description:\n 'AI engines use URL text as a content signal. Descriptive slugs help agents understand page topics before fetching the content.',\n code: '<!-- Use: /how-to-optimize-for-ai/ instead of /post-123/ -->',\n },\n );\n }\n\n const badUrls: string[] = [];\n\n for (const p of ctx.pages) {\n for (const pattern of BAD_SLUG_PATTERNS) {\n if (pattern.test(p.url)) {\n badUrls.push(p.url);\n break;\n }\n }\n }\n\n if (badUrls.length === 0) {\n return this.pass(\n `All ${ctx.pages.length} scanned page URL(s) use descriptive slugs.`,\n 'Page URLs use readable slugs (no UUIDs, no /post-123/, no encoded params)',\n ctx.pages\n .slice(0, 3)\n .map((p) => p.url)\n .join(', '),\n page.url,\n );\n }\n\n if (badUrls.length < ctx.pages.length) {\n return this.warn(\n `${badUrls.length} of ${ctx.pages.length} page(s) have non-descriptive URL slugs.`,\n 'Page URLs use readable slugs (no UUIDs, no /post-123/, no encoded params)',\n badUrls.slice(0, 3).join(', '),\n {\n priority: 'medium',\n description:\n \"AI engines use URL text as a pre-fetch topic signal and display URLs in generated citations. Non-descriptive slugs with UUIDs or numeric IDs provide no topical context, reducing your content's relevance score before the page is even crawled. Replace with keyword-rich slugs.\",\n code: '<!-- Change /post-123/ to /how-to-optimize-for-ai-agents/ -->',\n },\n badUrls[0],\n );\n }\n\n return this.fail(\n 'All scanned page URLs have non-descriptive slugs.',\n 'Page URLs use readable slugs (no UUIDs, no /post-123/, no encoded params)',\n badUrls.slice(0, 3).join(', '),\n {\n priority: 'high',\n description:\n 'AI engines use URL text as a pre-fetch topic signal and display URLs in generated citations. All your scanned pages have non-descriptive slugs (UUIDs, numeric IDs), providing zero topical context. Restructure to keyword-rich slugs that describe the page content.',\n code: '<!-- Change:\\n /post-123/ -> /how-to-optimize-for-ai/\\n /p/456/ -> /pricing-comparison/\\n /?id=789 -> /getting-started-guide/ -->',\n },\n badUrls[0],\n );\n }\n}\n","import type { AuditMeta } from './types';\nimport type { Audit } from './audit';\n\n// ── Category Config ─────────────────────────────────────────────\n\nexport interface CategoryConfig {\n id: string;\n name: string;\n /** Weight in the overall score (all weights should sum to 1.0). */\n weight: number;\n}\n\n// ── Audit Registration ──────────────────────────────────────────\n\nexport interface AuditRegistration {\n /** Construct an audit instance. */\n create: () => Audit;\n /** The audit's static meta (copied here for fast access without instantiation). */\n meta: AuditMeta;\n}\n\nexport interface ScanConfig {\n categories: CategoryConfig[];\n /** categoryId → list of audit registrations */\n audits: Record<string, AuditRegistration[]>;\n}\n\n// ── Helper ──────────────────────────────────────────────────────\n\nfunction reg(AuditClass: typeof Audit): AuditRegistration {\n return {\n create: () => new (AuditClass as unknown as new () => Audit)(),\n meta: AuditClass.meta,\n };\n}\n\n// ── Imports ─────────────────────────────────────────────────────\n\n// Content Discoverability (22)\nimport {\n LlmsTxtExistsAudit,\n LlmsTxtBlockquoteAudit,\n LlmsTxtSectionsAudit,\n LlmsTxtLinkDescriptionsAudit,\n LlmsTxtLinksValidAudit,\n LlmsFullTxtAudit,\n SitemapExistsAudit,\n SitemapKeyPagesAudit,\n SitemapAbsoluteUrlsAudit,\n SitemapLastmodAudit,\n RssFeedAudit,\n RssFeedContentAudit,\n NoNoindexAudit,\n NoNofollowAudit,\n InternalLinkingAudit,\n NoRedirectChainsAudit,\n CanonicalLinksAudit,\n MobileFriendlyAudit,\n FastPageLoadAudit,\n NoBrokenLinksAudit,\n NavigationJsonAudit,\n NoOrphanPagesAudit,\n CommerceLinksAudit,\n} from './audits/content-discoverability';\n\n// Crawler Permissions (26)\nimport {\n GptbotAudit,\n GoogleExtendedAudit,\n AnthropicAudit,\n PerplexitybotAudit,\n ApplebotExtendedAudit,\n CcbotAudit,\n MetaExternalAgentAudit,\n AmazonbotAudit,\n BytespiderAudit,\n CohereAiAudit,\n YoubotAudit,\n DiffbotAudit,\n Ai2botAudit,\n ChatgptUserAudit,\n ClaudeUserAudit,\n OaiSearchbotAudit,\n MetaExternalFetcherAudit,\n BravebotAudit,\n DuckassistbotAudit,\n MistralaiUserAudit,\n ClaudeSearchbotAudit,\n NoBlanketBlockAudit,\n SensitivePathsAudit,\n CrawlDelayAudit,\n MetaRobotsNotBlockingAudit,\n NoBotDetectionAudit,\n} from './audits/crawler-permissions';\n\n// Structured Data (16)\nimport {\n JsonLdPresentAudit,\n SchemaValidationAudit,\n OrganizationSchemaAudit,\n WebSiteSearchActionAudit,\n BreadcrumbSchemaAudit,\n ArticleSchemaAudit,\n FaqPageSchemaAudit,\n ServiceProductSchemaAudit,\n SpeakableSchemaAudit,\n PotentialActionAudit,\n HowToSchemaAudit,\n LocalBusinessSchemaAudit,\n ReviewSchemaAudit,\n OfferSchemaAudit,\n AuthorSchemaAudit,\n ActionSchemaAudit,\n ProductIdentifiersAudit,\n ProductDetailsAudit,\n ProductReviewsAudit,\n} from './audits/structured-data';\n\n// Meta Tags (20)\nimport {\n MetaDescriptionAudit,\n MetaAuthorAudit,\n CanonicalUrlAudit,\n LanguageAttributeAudit,\n UniqueMetaAudit,\n CoreOpenGraphAudit,\n OgTypeAudit,\n OgSiteNameAudit,\n OgImageAltAudit,\n TwitterCardAudit,\n LlmsTxtLinkAudit,\n LlmsFullTxtLinkAudit,\n AiContentDeclarationAudit,\n AiInstructionsAudit,\n MarkdownAlternateAudit,\n RssFeedLinkAudit,\n McpDiscoveryLinkAudit,\n OpenApiLinkAudit,\n AiCatalogLinkAudit,\n MetaRobotsAudit,\n} from './audits/meta-tags';\n\n// Agent Tools (25)\nimport {\n OpenApiExistsAudit,\n OpenApiEndpointsAudit,\n OpenApiOperationIdsAudit,\n OpenApiAiInstructionsAudit,\n OpenApiServersAudit,\n OpenApiSchemasAudit,\n AiCatalogExistsAudit,\n AiCatalogMetadataAudit,\n AiCatalogUrlsAudit,\n AgentsJsonAudit,\n AiPluginJsonAudit,\n McpDiscoveryAudit,\n McpEndpointAudit,\n McpCapabilitiesAudit,\n ContactFormAudit,\n SearchEndpointAudit,\n DataActionCtasAudit,\n NoBlockingCaptchaAudit,\n FormsNoJsAudit,\n WebmcpManifestAudit,\n WebmcpDeclarativeFormsAudit,\n WebmcpInputQualityAudit,\n WebmcpToolNamingAudit,\n WebmcpToolAnnotationsAudit,\n WebmcpActionCoverageAudit,\n} from './audits/agent-tools';\n\n// Semantic HTML (17)\nimport {\n SingleH1Audit,\n SequentialHeadingsAudit,\n MainElementAudit,\n ArticleElementAudit,\n HeaderFooterAudit,\n AsideElementAudit,\n SectionHeadingsAudit,\n SemanticListsAudit,\n DataTablesAudit,\n CodeLanguageAudit,\n TimeElementAudit,\n AddressElementAudit,\n DefinitionElementsAudit,\n ContentDepthAudit,\n ImageAltTextAudit,\n DecorativeImagesAudit,\n FigureFigcaptionAudit,\n} from './audits/semantic-html';\n\n// Accessibility — hand-rolled markup audits + engine-backed tree audits (23)\nimport {\n SkipNavAudit,\n AriaLandmarksAudit,\n NavAriaLabelAudit,\n FormErrorMessagesAudit,\n A11yLandmarkUniqueAudit,\n A11yFormLabelsAudit,\n A11yAccessibleNamesAudit,\n A11yDialogNameAudit,\n A11yAriaHiddenBodyAudit,\n A11yAriaRolesAudit,\n A11yAriaAttributesAudit,\n A11yAriaRelationshipsAudit,\n A11yDuplicateIdAudit,\n A11yAutocompleteAudit,\n A11yNestedInteractiveAudit,\n A11yTableHeadersAudit,\n A11yDocumentTitleAudit,\n A11yFrameTitleAudit,\n A11yMetaRefreshAudit,\n A11yTabindexAudit,\n A11yDeprecatedElementsAudit,\n A11yPresentationConflictAudit,\n} from './audits/accessibility';\n\n// Technical Readiness (20)\nimport {\n HttpsEnabledAudit,\n HstsHeaderAudit,\n CspHeaderAudit,\n ContentTypeOptionsAudit,\n ReferrerPolicyAudit,\n PermissionsPolicyAudit,\n SecurityTxtAudit,\n CorsAiFilesAudit,\n CorsApiRoutesAudit,\n CorrectContentTypesAudit,\n CacheHeadersAudit,\n FastResponseTimeAudit,\n ServerRenderedAudit,\n NoRenderBlockingAudit,\n ImageDimensionsAudit,\n LcpNotLazyAudit,\n PreconnectHintsAudit,\n NoBrokenAiEndpointsAudit,\n PrivacyPolicyAudit,\n TermsOfServiceAudit,\n FrameworkDetectionAudit,\n} from './audits/technical-readiness';\n\n// Answer Engine (11)\nimport {\n FaqSectionsAudit,\n QuestionHeadingsAudit,\n FirstParagraphAnswersAudit,\n DirectDefinitionsAudit,\n ComparisonTablesAudit,\n NumberedStepsAudit,\n SpecificNumbersAudit,\n DatesOnContentAudit,\n ContentWithoutClickthroughAudit,\n LastUpdatedIndicatorAudit,\n MetaDescriptionAeoAudit,\n} from './audits/answer-engine';\n\n// Generative Engine (15)\nimport {\n NamedAuthorAudit,\n AuthorSameAsAudit,\n AuthorPageAudit,\n AboutCredentialsAudit,\n ExternalCitationsAudit,\n BrandNameAudit,\n TrustSignalsAudit,\n ReviewSignalsAudit,\n PublicationDateAudit,\n LastModifiedSchemaAudit,\n InternalCrossLinkingAudit,\n PaginationLinksAudit,\n UniqueDataAudit,\n BlockquoteUsageAudit,\n DescriptiveUrlsAudit,\n} from './audits/generative-engine';\n\n// ── Default Config ──────────────────────────────────────────────\n\nexport const defaultConfig: ScanConfig = {\n categories: [\n { id: 'content-discoverability', name: 'Content Discoverability', weight: 0.15 },\n { id: 'crawler-permissions', name: 'AI Crawler Permissions', weight: 0.08 },\n { id: 'structured-data', name: 'Structured Data & Schema Markup', weight: 0.12 },\n { id: 'meta-tags', name: 'Meta Tags & AI Head Elements', weight: 0.08 },\n { id: 'agent-tools', name: 'AI Agent Tools & Action Surfaces', weight: 0.18 },\n { id: 'semantic-html', name: 'Semantic HTML & Content Structure', weight: 0.08 },\n { id: 'accessibility', name: 'Accessibility & Agent Interaction', weight: 0.07 },\n { id: 'technical-readiness', name: 'Technical Readiness & Security', weight: 0.09 },\n { id: 'answer-engine', name: 'Answer Engine Optimization', weight: 0.07 },\n { id: 'generative-engine', name: 'Generative Engine Optimization', weight: 0.08 },\n ],\n audits: {\n 'content-discoverability': [\n reg(LlmsTxtExistsAudit),\n reg(LlmsTxtBlockquoteAudit),\n reg(LlmsTxtSectionsAudit),\n reg(LlmsTxtLinkDescriptionsAudit),\n reg(LlmsTxtLinksValidAudit),\n reg(LlmsFullTxtAudit),\n reg(SitemapExistsAudit),\n reg(SitemapKeyPagesAudit),\n reg(SitemapAbsoluteUrlsAudit),\n reg(SitemapLastmodAudit),\n reg(RssFeedAudit),\n reg(RssFeedContentAudit),\n reg(NoNoindexAudit),\n reg(NoNofollowAudit),\n reg(InternalLinkingAudit),\n reg(NoRedirectChainsAudit),\n reg(CanonicalLinksAudit),\n reg(MobileFriendlyAudit),\n reg(FastPageLoadAudit),\n reg(NoBrokenLinksAudit),\n reg(NavigationJsonAudit),\n reg(NoOrphanPagesAudit),\n reg(CommerceLinksAudit),\n ],\n 'crawler-permissions': [\n reg(GptbotAudit),\n reg(GoogleExtendedAudit),\n reg(AnthropicAudit),\n reg(PerplexitybotAudit),\n reg(ApplebotExtendedAudit),\n reg(CcbotAudit),\n reg(MetaExternalAgentAudit),\n reg(AmazonbotAudit),\n reg(BytespiderAudit),\n reg(CohereAiAudit),\n reg(YoubotAudit),\n reg(DiffbotAudit),\n reg(Ai2botAudit),\n reg(ChatgptUserAudit),\n reg(ClaudeUserAudit),\n reg(OaiSearchbotAudit),\n reg(MetaExternalFetcherAudit),\n reg(BravebotAudit),\n reg(DuckassistbotAudit),\n reg(MistralaiUserAudit),\n reg(ClaudeSearchbotAudit),\n reg(NoBlanketBlockAudit),\n reg(SensitivePathsAudit),\n reg(CrawlDelayAudit),\n reg(MetaRobotsNotBlockingAudit),\n reg(NoBotDetectionAudit),\n ],\n 'structured-data': [\n reg(JsonLdPresentAudit),\n reg(SchemaValidationAudit),\n reg(OrganizationSchemaAudit),\n reg(WebSiteSearchActionAudit),\n reg(BreadcrumbSchemaAudit),\n reg(ArticleSchemaAudit),\n reg(FaqPageSchemaAudit),\n reg(ServiceProductSchemaAudit),\n reg(SpeakableSchemaAudit),\n reg(PotentialActionAudit),\n reg(HowToSchemaAudit),\n reg(LocalBusinessSchemaAudit),\n reg(ReviewSchemaAudit),\n reg(OfferSchemaAudit),\n reg(AuthorSchemaAudit),\n reg(ActionSchemaAudit),\n reg(ProductIdentifiersAudit),\n reg(ProductDetailsAudit),\n reg(ProductReviewsAudit),\n ],\n 'meta-tags': [\n reg(MetaDescriptionAudit),\n reg(MetaAuthorAudit),\n reg(CanonicalUrlAudit),\n reg(LanguageAttributeAudit),\n reg(UniqueMetaAudit),\n reg(CoreOpenGraphAudit),\n reg(OgTypeAudit),\n reg(OgSiteNameAudit),\n reg(OgImageAltAudit),\n reg(TwitterCardAudit),\n reg(LlmsTxtLinkAudit),\n reg(LlmsFullTxtLinkAudit),\n reg(AiContentDeclarationAudit),\n reg(AiInstructionsAudit),\n reg(MarkdownAlternateAudit),\n reg(RssFeedLinkAudit),\n reg(McpDiscoveryLinkAudit),\n reg(OpenApiLinkAudit),\n reg(AiCatalogLinkAudit),\n reg(MetaRobotsAudit),\n ],\n 'agent-tools': [\n reg(OpenApiExistsAudit),\n reg(OpenApiEndpointsAudit),\n reg(OpenApiOperationIdsAudit),\n reg(OpenApiAiInstructionsAudit),\n reg(OpenApiServersAudit),\n reg(OpenApiSchemasAudit),\n reg(AiCatalogExistsAudit),\n reg(AiCatalogMetadataAudit),\n reg(AiCatalogUrlsAudit),\n reg(AgentsJsonAudit),\n reg(AiPluginJsonAudit),\n reg(McpDiscoveryAudit),\n reg(McpEndpointAudit),\n reg(McpCapabilitiesAudit),\n reg(ContactFormAudit),\n reg(SearchEndpointAudit),\n reg(DataActionCtasAudit),\n reg(NoBlockingCaptchaAudit),\n reg(FormsNoJsAudit),\n reg(WebmcpManifestAudit),\n reg(WebmcpDeclarativeFormsAudit),\n reg(WebmcpInputQualityAudit),\n reg(WebmcpToolNamingAudit),\n reg(WebmcpToolAnnotationsAudit),\n reg(WebmcpActionCoverageAudit),\n ],\n 'semantic-html': [\n reg(SingleH1Audit),\n reg(SequentialHeadingsAudit),\n reg(MainElementAudit),\n reg(ArticleElementAudit),\n reg(HeaderFooterAudit),\n reg(AsideElementAudit),\n reg(SectionHeadingsAudit),\n reg(SemanticListsAudit),\n reg(DataTablesAudit),\n reg(CodeLanguageAudit),\n reg(TimeElementAudit),\n reg(AddressElementAudit),\n reg(DefinitionElementsAudit),\n reg(ContentDepthAudit),\n reg(ImageAltTextAudit),\n reg(DecorativeImagesAudit),\n reg(FigureFigcaptionAudit),\n ],\n accessibility: [\n reg(SkipNavAudit),\n reg(AriaLandmarksAudit),\n reg(NavAriaLabelAudit),\n reg(FormErrorMessagesAudit),\n reg(A11yLandmarkUniqueAudit),\n reg(A11yFormLabelsAudit),\n reg(A11yAccessibleNamesAudit),\n reg(A11yDialogNameAudit),\n reg(A11yAriaHiddenBodyAudit),\n reg(A11yAriaRolesAudit),\n reg(A11yAriaAttributesAudit),\n reg(A11yAriaRelationshipsAudit),\n reg(A11yDuplicateIdAudit),\n reg(A11yAutocompleteAudit),\n reg(A11yNestedInteractiveAudit),\n reg(A11yTableHeadersAudit),\n reg(A11yDocumentTitleAudit),\n reg(A11yFrameTitleAudit),\n reg(A11yMetaRefreshAudit),\n reg(A11yTabindexAudit),\n reg(A11yDeprecatedElementsAudit),\n reg(A11yPresentationConflictAudit),\n ],\n 'technical-readiness': [\n reg(HttpsEnabledAudit),\n reg(HstsHeaderAudit),\n reg(CspHeaderAudit),\n reg(ContentTypeOptionsAudit),\n reg(ReferrerPolicyAudit),\n reg(PermissionsPolicyAudit),\n reg(SecurityTxtAudit),\n reg(CorsAiFilesAudit),\n reg(CorsApiRoutesAudit),\n reg(CorrectContentTypesAudit),\n reg(CacheHeadersAudit),\n reg(FastResponseTimeAudit),\n reg(ServerRenderedAudit),\n reg(NoRenderBlockingAudit),\n reg(ImageDimensionsAudit),\n reg(LcpNotLazyAudit),\n reg(PreconnectHintsAudit),\n reg(NoBrokenAiEndpointsAudit),\n reg(PrivacyPolicyAudit),\n reg(TermsOfServiceAudit),\n reg(FrameworkDetectionAudit),\n ],\n 'answer-engine': [\n reg(FaqSectionsAudit),\n reg(QuestionHeadingsAudit),\n reg(FirstParagraphAnswersAudit),\n reg(DirectDefinitionsAudit),\n reg(ComparisonTablesAudit),\n reg(NumberedStepsAudit),\n reg(SpecificNumbersAudit),\n reg(DatesOnContentAudit),\n reg(ContentWithoutClickthroughAudit),\n reg(LastUpdatedIndicatorAudit),\n reg(MetaDescriptionAeoAudit),\n ],\n 'generative-engine': [\n reg(NamedAuthorAudit),\n reg(AuthorSameAsAudit),\n reg(AuthorPageAudit),\n reg(AboutCredentialsAudit),\n reg(ExternalCitationsAudit),\n reg(BrandNameAudit),\n reg(TrustSignalsAudit),\n reg(ReviewSignalsAudit),\n reg(PublicationDateAudit),\n reg(LastModifiedSchemaAudit),\n reg(InternalCrossLinkingAudit),\n reg(PaginationLinksAudit),\n reg(UniqueDataAudit),\n reg(BlockquoteUsageAudit),\n reg(DescriptiveUrlsAudit),\n ],\n },\n};\n","import type { CheckResult, CategoryResult, PageType, AuditMeta } from './types';\nimport { logger } from './logger';\nimport { TAG_SKIPPED_PAGE_TYPE, TAG_SCAN_ERROR } from './constants';\nimport type { CheckContext } from './check-context';\nimport type { ScanConfig, CategoryConfig, AuditRegistration } from './audit-config';\n\n/**\n * Build a not-applicable stub for an audit that never produced a real verdict,\n * so it stays visible in the report (tagged with why) instead of vanishing.\n */\nfunction stubCheck(meta: AuditMeta, tag: string, explanation: string): CheckResult {\n return {\n id: meta.id,\n category: meta.category,\n title: meta.title,\n description: meta.description,\n status: 'na',\n score: 0,\n scoreDisplayMode: meta.scoreDisplayMode,\n explanation,\n priority: meta.defaultPriority,\n impact: meta.guidance?.impact ?? '',\n fix: meta.guidance?.fix ?? '',\n tags: [tag],\n };\n}\n\nexport interface AuditRunResult {\n checks: CheckResult[];\n categories: CategoryResult[];\n overallScore: number;\n}\n\ntype ProgressFn = (completed: number, total: number) => void;\n\n/**\n * Execute all audits registered in the config against the scan context.\n * Returns check results grouped into categories with weighted scores.\n */\nexport async function runAudits(\n ctx: CheckContext,\n config: ScanConfig,\n onProgress?: ProgressFn,\n): Promise<AuditRunResult> {\n // Collect the set of page types present in the scan context\n const scannedPageTypes = new Set(ctx.pages.map((p) => p.pageType));\n\n // Flatten all registrations for batched execution. Audits whose\n // applicablePageTypes don't match any scanned page type are not executed, but\n // recorded as `na` stubs so they remain visible in the report.\n const all: Array<{ reg: AuditRegistration; categoryId: string }> = [];\n const allChecks: CheckResult[] = [];\n for (const cat of config.categories) {\n const regs = config.audits[cat.id] ?? [];\n for (const reg of regs) {\n const applicable = reg.meta.applicablePageTypes;\n if (applicable && applicable.length > 0) {\n if (!applicable.some((pt: PageType) => scannedPageTypes.has(pt))) {\n allChecks.push(\n stubCheck(\n reg.meta,\n TAG_SKIPPED_PAGE_TYPE,\n `Not applicable: no scanned page is of type ${applicable.join('/')}.`,\n ),\n );\n continue;\n }\n }\n all.push({ reg, categoryId: cat.id });\n }\n }\n\n const totalAudits = all.length;\n let completed = 0;\n\n // Run in batches of 20 (same concurrency as before)\n const batchSize = 20;\n for (let i = 0; i < totalAudits; i += batchSize) {\n const batch = all.slice(i, i + batchSize);\n const batchResults = await Promise.all(\n batch.map(async ({ reg }) => {\n try {\n const instance = reg.create();\n const result = await instance.audit(ctx);\n return instance.toCheckResult(result);\n } catch (err) {\n // Don't silently drop a throwing audit — record it as an errored\n // `na` stub so it stays visible in the report and in coverage.\n logger.error({ err, auditId: reg.meta.id }, '[scanner] Audit error');\n const message = err instanceof Error ? err.message : String(err);\n return stubCheck(reg.meta, TAG_SCAN_ERROR, `Audit failed to run: ${message}`);\n }\n }),\n );\n\n allChecks.push(...batchResults);\n completed += batchResults.length;\n onProgress?.(completed, totalAudits);\n }\n\n // Build category results\n const categories = config.categories.map((cat) => {\n const catChecks = allChecks.filter((c) => c.category === cat.id);\n const catRegs = config.audits[cat.id] ?? [];\n return buildWeightedCategoryResult(cat, catChecks, catRegs);\n });\n\n const overallScore = Math.round(categories.reduce((sum, cat) => sum + cat.score * cat.weight, 0));\n\n return { checks: allChecks, categories, overallScore };\n}\n\nfunction buildWeightedCategoryResult(\n cat: CategoryConfig,\n checks: CheckResult[],\n registrations: AuditRegistration[],\n): CategoryResult {\n if (checks.length === 0) {\n return {\n id: cat.id,\n name: cat.name,\n weight: cat.weight,\n score: 0,\n checks,\n passCount: 0,\n warnCount: 0,\n failCount: 0,\n };\n }\n\n // Build weight map: auditId → weight\n const weightMap = new Map<string, number>();\n for (const reg of registrations) {\n weightMap.set(reg.meta.id, reg.meta.weight);\n }\n\n // Not-applicable checks represent \"nothing to assess\" — exclude them from the\n // weighted average so they don't deflate the category score.\n let totalWeight = 0;\n let weightedSum = 0;\n for (const check of checks) {\n if (check.status === 'na') continue;\n const w = weightMap.get(check.id) ?? 1.0;\n weightedSum += check.score * w;\n totalWeight += w;\n }\n\n const score = totalWeight > 0 ? Math.round((weightedSum / totalWeight) * 100) : 0;\n\n return {\n id: cat.id,\n name: cat.name,\n weight: cat.weight,\n score,\n checks,\n passCount: checks.filter((c) => c.status === 'pass').length,\n warnCount: checks.filter((c) => c.status === 'warn').length,\n failCount: checks.filter((c) => c.status === 'fail').length,\n };\n}\n","/**\n * Accessibility rule runner.\n *\n * Runs a vendored subset of axe-core's accessibility checks over a page's static\n * HTML using jsdom (no browser). We adopt only the rules that describe how an AI\n * agent reads/acts on a page via the accessibility tree — programmatic roles,\n * names, relationships, structure — NOT human-perception rules (color contrast,\n * focus visibility, target size), which a non-human consumer doesn't care about.\n *\n * Previously this injected the full ~1.2MB axe-core runtime into each jsdom\n * window. The check/commons/standards logic for the 26 supported rules is now\n * vendored in `./engine` (ported from axe-core v4.12.1) and runs directly against\n * the parsed DOM, so the `axe-core` npm dependency is no longer needed.\n */\nimport { JSDOM } from 'jsdom';\nimport { logger } from '../../logger';\nimport { runRules } from './engine/rules';\n\nexport interface A11yNodeFinding {\n target: string;\n summary: string;\n}\n\nexport type A11yStatus = 'pass' | 'fail' | 'incomplete' | 'inapplicable';\n\nexport interface A11yRuleResult {\n status: A11yStatus;\n nodes: A11yNodeFinding[];\n}\n\n/** ruleId → result for a single page. */\nexport type A11yPageResult = Record<string, A11yRuleResult>;\n\n// Bound how many jsdom instances are alive at once (process-wide) to cap memory\n// under concurrent scans. Each run is independent, so this is a throughput\n// limiter, not a correctness lock.\nconst MAX_CONCURRENT_A11Y = Math.max(1, Number(process.env.A11Y_CONCURRENCY ?? 3));\nlet activeA11y = 0;\nconst a11yQueue: Array<() => void> = [];\nasync function acquire(): Promise<void> {\n if (activeA11y < MAX_CONCURRENT_A11Y) {\n activeA11y++;\n return;\n }\n await new Promise<void>((resolve) => a11yQueue.push(resolve));\n activeA11y++;\n}\nfunction release(): void {\n activeA11y--;\n a11yQueue.shift()?.();\n}\n\n/**\n * Strip `<style>` blocks and stylesheet `<link>`s from an HTML string.\n *\n * jsdom parses every inline stylesheet into CSSOM *synchronously* when the\n * document is constructed — real storefronts ship hundreds of KB of inline CSS\n * across dozens of `<style>` blocks, which grinds the event loop for seconds\n * (and floods logs with \"Could not parse CSS stylesheet\"). None of our adopted\n * rules read CSS or layout (contrast/focus-visibility are deliberately\n * excluded, and jsdom has no layout engine anyway), so this CSS is pure dead\n * weight. Inline `style=\"…\"` attributes are left intact — they carry per-element\n * state some rules inspect and cost nothing to keep.\n */\nexport function stripStyles(html: string): string {\n return html\n .replace(/<style\\b[^>]*>[\\s\\S]*?<\\/style>/gi, '')\n .replace(/<link\\b[^>]*\\brel\\s*=\\s*[\"']?stylesheet\\b[^>]*>/gi, '');\n}\n\n/**\n * Run the given accessibility rule ids over one HTML document. Returns a map of\n * ruleId → {status, nodes}. Never throws — on any jsdom/internal failure it logs\n * and returns an empty map so the calling audits degrade to \"not applicable\".\n */\nexport async function runA11yForHtml(\n html: string,\n url: string,\n ruleIds: string[],\n): Promise<A11yPageResult> {\n await acquire();\n let dom: JSDOM | undefined;\n try {\n dom = new JSDOM(stripStyles(html), { url, runScripts: 'outside-only', pretendToBeVisual: true });\n const doc = dom.window.document as unknown as Document;\n const results = runRules(doc, ruleIds);\n\n const out: A11yPageResult = {};\n for (const id of ruleIds) {\n const r = results[id];\n if (!r) continue;\n out[id] = {\n status: r.status,\n nodes: r.nodes.slice(0, 5).map((n) => ({\n target: n.target,\n summary: (n.summary ?? '').replace(/\\s+/g, ' ').trim(),\n })),\n };\n }\n return out;\n } catch (err) {\n logger.warn({ err, url }, '[a11y-runner] accessibility run failed; treating rules as not-applicable');\n return {};\n } finally {\n try {\n dom?.window.close();\n } catch {\n /* ignore */\n }\n release();\n }\n}\n","/**\n * Vendored axe-core v4.12.1 standards data (pure data tables, copied verbatim).\n * These describe ARIA roles/attributes and the HTML element spec used by the\n * accessibility checks. Loose typing (Record<string, any>) is intentional.\n */\n/* eslint-disable */\n// oxlint-disable\n\n// Source: https://www.w3.org/TR/wai-aria-1.1/#states_and_properties\nconst ariaAttrs: Record<string, any> = {\n 'aria-activedescendant': {\n type: 'idref',\n prop: 'ariaActiveDescendantElement',\n allowEmpty: true\n },\n 'aria-atomic': {\n type: 'boolean',\n prop: 'ariaAtomic',\n global: true\n },\n 'aria-autocomplete': {\n type: 'nmtoken',\n prop: 'ariaAutoComplete',\n values: ['inline', 'list', 'both', 'none']\n },\n 'aria-braillelabel': {\n type: 'string',\n prop: 'ariaBrailleLabel',\n allowEmpty: true,\n global: true\n },\n 'aria-brailleroledescription': {\n type: 'string',\n prop: 'ariaBrailleRoleDescription',\n allowEmpty: true,\n global: true\n },\n 'aria-busy': {\n type: 'boolean',\n prop: 'ariaBusy',\n global: true\n },\n 'aria-checked': {\n type: 'nmtoken',\n prop: 'ariaChecked',\n values: ['false', 'mixed', 'true', 'undefined']\n },\n 'aria-colcount': {\n type: 'int',\n prop: 'ariaColCount',\n minValue: -1\n },\n 'aria-colindex': {\n type: 'int',\n prop: 'ariaColIndex',\n minValue: 1\n },\n 'aria-colspan': {\n type: 'int',\n prop: 'ariaColSpan',\n minValue: 1\n },\n 'aria-controls': {\n type: 'idrefs',\n prop: 'ariaControlsElements',\n allowEmpty: true,\n global: true\n },\n 'aria-current': {\n type: 'nmtoken',\n prop: 'ariaCurrent',\n allowEmpty: true,\n values: ['page', 'step', 'location', 'date', 'time', 'true', 'false'],\n global: true\n },\n 'aria-describedby': {\n type: 'idrefs',\n prop: 'ariaDescribedByElements',\n allowEmpty: true,\n global: true\n },\n 'aria-description': {\n type: 'string',\n prop: 'ariaDescription',\n allowEmpty: true,\n global: true\n },\n 'aria-details': {\n type: 'idref',\n prop: 'ariaDetailsElements',\n allowEmpty: true,\n global: true\n },\n 'aria-disabled': {\n type: 'boolean',\n prop: 'ariaDisabled',\n global: true\n },\n 'aria-dropeffect': {\n type: 'nmtokens',\n values: ['copy', 'execute', 'link', 'move', 'none', 'popup'],\n global: true\n },\n 'aria-errormessage': {\n type: 'idref',\n prop: 'ariaErrorMessageElements',\n allowEmpty: true,\n global: true\n },\n 'aria-expanded': {\n type: 'nmtoken',\n prop: 'ariaExpanded',\n values: ['true', 'false', 'undefined']\n },\n 'aria-flowto': {\n type: 'idrefs',\n prop: 'ariaFlowToElements',\n allowEmpty: true,\n global: true\n },\n 'aria-grabbed': {\n type: 'nmtoken',\n values: ['true', 'false', 'undefined'],\n global: true\n },\n 'aria-haspopup': {\n type: 'nmtoken',\n prop: 'ariaHasPopup',\n allowEmpty: true,\n values: ['true', 'false', 'menu', 'listbox', 'tree', 'grid', 'dialog'],\n global: true\n },\n 'aria-hidden': {\n type: 'nmtoken',\n prop: 'ariaHidden',\n values: ['true', 'false', 'undefined'],\n global: true\n },\n 'aria-invalid': {\n type: 'nmtoken',\n prop: 'ariaInvalid',\n values: ['grammar', 'false', 'spelling', 'true'],\n global: true\n },\n 'aria-keyshortcuts': {\n type: 'string',\n prop: 'ariaKeyShortcuts',\n allowEmpty: true,\n global: true\n },\n 'aria-label': {\n type: 'string',\n prop: 'ariaLabel',\n allowEmpty: true,\n global: true\n },\n 'aria-labelledby': {\n type: 'idrefs',\n prop: 'ariaLabelledByElements',\n allowEmpty: true,\n global: true\n },\n 'aria-level': {\n type: 'int',\n prop: 'ariaLevel',\n minValue: 1\n },\n 'aria-live': {\n type: 'nmtoken',\n prop: 'ariaLive',\n values: ['assertive', 'off', 'polite'],\n global: true\n },\n 'aria-modal': {\n type: 'boolean',\n prop: 'ariaModal'\n },\n 'aria-multiline': {\n type: 'boolean',\n prop: 'ariaMultiline'\n },\n 'aria-multiselectable': {\n type: 'boolean',\n prop: 'ariaMultiSelectable'\n },\n 'aria-orientation': {\n type: 'nmtoken',\n prop: 'ariaOrientation',\n values: ['horizontal', 'undefined', 'vertical']\n },\n 'aria-owns': {\n type: 'idrefs',\n prop: 'ariaOwnsElements',\n allowEmpty: true,\n global: true\n },\n 'aria-placeholder': {\n type: 'string',\n prop: 'ariaPlaceholder',\n allowEmpty: true\n },\n 'aria-posinset': {\n type: 'int',\n prop: 'ariaPosInSet',\n minValue: 1\n },\n 'aria-pressed': {\n type: 'nmtoken',\n prop: 'ariaPressed',\n values: ['false', 'mixed', 'true', 'undefined']\n },\n 'aria-readonly': {\n type: 'boolean',\n prop: 'ariaReadOnly'\n },\n 'aria-relevant': {\n type: 'nmtokens',\n prop: 'ariaRelevant',\n values: ['additions', 'all', 'removals', 'text'],\n global: true\n },\n 'aria-required': {\n type: 'boolean',\n prop: 'ariaRequired'\n },\n 'aria-roledescription': {\n type: 'string',\n prop: 'ariaRoleDescription',\n allowEmpty: true,\n global: true\n },\n 'aria-rowcount': {\n type: 'int',\n prop: 'ariaRowCount',\n minValue: -1\n },\n 'aria-rowindex': {\n type: 'int',\n prop: 'ariaRowIndex',\n minValue: 1\n },\n 'aria-rowspan': {\n type: 'int',\n prop: 'ariaRowSpan',\n minValue: 0\n },\n 'aria-selected': {\n type: 'nmtoken',\n prop: 'ariaSelected',\n values: ['false', 'true', 'undefined']\n },\n 'aria-setsize': {\n type: 'int',\n prop: 'ariaSetSize',\n minValue: -1\n },\n 'aria-sort': {\n type: 'nmtoken',\n prop: 'ariaSort',\n values: ['ascending', 'descending', 'none', 'other']\n },\n 'aria-valuemax': {\n type: 'decimal',\n prop: 'ariaValueMax'\n },\n 'aria-valuemin': {\n type: 'decimal',\n prop: 'ariaValueMin'\n },\n 'aria-valuenow': {\n type: 'decimal',\n prop: 'ariaValueNow'\n },\n 'aria-valuetext': {\n type: 'string',\n prop: 'ariaValueText',\n allowEmpty: true\n }\n};\n\nexport { ariaAttrs };\n\n// Source: https://www.w3.org/TR/wai-aria-1.1/#roles\n// Source for abstract roles (types): https://www.w3.org/TR/wai-aria/#abstract_roles\n\n/* easiest way to see allowed roles is to filter out the global ones\n from the list of inherited states and properties. The dpub spec\n does not have the global list so you'll need to copy over from\n the wai-aria one:\n\n const globalAttrs = Array.from(\n document.querySelectorAll('#global_states li')\n ).map(li => li.textContent.replace(/\\s*\\(.*\\)/, ''));\n\n const globalRoleAttrs = Array.from(\n document.querySelectorAll('.role-inherited li')\n ).filter(li => globalAttrs.includes(li.textContent.replace(/\\s*\\(.*\\)/, '')))\n\n globalRoleAttrs.forEach(li => li.style.display = 'none');\n*/\nconst ariaRolesBase: Record<string, any> = {\n alert: {\n type: 'structure',\n // Spec difference: Aria-expanded removed in 1.2\n allowedAttrs: ['aria-expanded'],\n superclassRole: ['section']\n },\n alertdialog: {\n type: 'window',\n // Spec difference: Aria-expanded removed in 1.2\n allowedAttrs: ['aria-expanded', 'aria-modal'],\n superclassRole: ['alert', 'dialog'],\n accessibleNameRequired: true\n },\n application: {\n // Note: spec difference\n type: 'landmark',\n // Note: aria-expanded is not in the 1.1 spec but is\n // consistently supported in ATs and was added in 1.2\n allowedAttrs: ['aria-activedescendant', 'aria-expanded'],\n superclassRole: ['structure'],\n accessibleNameRequired: true\n },\n article: {\n type: 'structure',\n // Spec difference: Aria-expanded removed in 1.2\n allowedAttrs: ['aria-posinset', 'aria-setsize', 'aria-expanded'],\n superclassRole: ['document']\n },\n banner: {\n type: 'landmark',\n // Spec difference: Aria-expanded removed in 1.2\n allowedAttrs: ['aria-expanded'],\n superclassRole: ['landmark']\n },\n blockquote: {\n type: 'structure',\n superclassRole: ['section']\n },\n button: {\n type: 'widget',\n allowedAttrs: ['aria-expanded', 'aria-pressed'],\n superclassRole: ['command'],\n accessibleNameRequired: true,\n nameFromContent: true,\n childrenPresentational: true\n },\n caption: {\n type: 'structure',\n requiredContext: ['figure', 'table', 'grid', 'treegrid'],\n superclassRole: ['section'],\n prohibitedAttrs: ['aria-label', 'aria-labelledby']\n },\n cell: {\n type: 'structure',\n requiredContext: ['row'],\n // Spec difference: Aria-expanded removed in 1.2\n allowedAttrs: [\n 'aria-colindex',\n 'aria-colspan',\n 'aria-rowindex',\n 'aria-rowspan',\n 'aria-expanded'\n ],\n superclassRole: ['section'],\n nameFromContent: true\n },\n checkbox: {\n type: 'widget',\n // Note: aria-required is not in the 1.1 spec but is\n // consistently supported in ATs and was added in 1.2\n requiredAttrs: ['aria-checked'],\n allowedAttrs: ['aria-readonly', 'aria-expanded', 'aria-required'],\n superclassRole: ['input'],\n accessibleNameRequired: true,\n nameFromContent: true,\n childrenPresentational: true\n },\n code: {\n type: 'structure',\n superclassRole: ['section'],\n prohibitedAttrs: ['aria-label', 'aria-labelledby']\n },\n columnheader: {\n type: 'structure',\n requiredContext: ['row'],\n // Spec difference: Aria-expanded removed in 1.2\n allowedAttrs: [\n 'aria-sort',\n 'aria-colindex',\n 'aria-colspan',\n 'aria-expanded',\n 'aria-readonly',\n 'aria-required',\n 'aria-rowindex',\n 'aria-rowspan',\n 'aria-selected'\n ],\n superclassRole: ['cell', 'gridcell', 'sectionhead'],\n // Note: spec difference\n accessibleNameRequired: false,\n nameFromContent: true\n },\n combobox: {\n // Note: spec difference\n type: 'widget',\n requiredAttrs: ['aria-expanded', 'aria-controls'],\n allowedAttrs: [\n 'aria-owns',\n 'aria-autocomplete',\n 'aria-readonly',\n 'aria-required',\n 'aria-activedescendant',\n 'aria-orientation'\n ],\n superclassRole: ['select'],\n accessibleNameRequired: true\n },\n command: {\n type: 'abstract',\n superclassRole: ['widget']\n },\n complementary: {\n type: 'landmark',\n // Spec difference: Aria-expanded removed in 1.2\n allowedAttrs: ['aria-expanded'],\n superclassRole: ['landmark']\n },\n composite: {\n type: 'abstract',\n superclassRole: ['widget']\n },\n contentinfo: {\n type: 'landmark',\n // Spec difference: Aria-expanded removed in 1.2\n allowedAttrs: ['aria-expanded'],\n superclassRole: ['landmark']\n },\n comment: {\n type: 'structure',\n allowedAttrs: ['aria-level', 'aria-posinset', 'aria-setsize'],\n superclassRole: ['article']\n },\n definition: {\n type: 'structure',\n // Spec difference: Aria-expanded removed in 1.2\n allowedAttrs: ['aria-expanded'],\n superclassRole: ['section']\n },\n deletion: {\n type: 'structure',\n superclassRole: ['section'],\n prohibitedAttrs: ['aria-label', 'aria-labelledby']\n },\n dialog: {\n type: 'window',\n // Spec difference: Aria-expanded removed in 1.2\n allowedAttrs: ['aria-expanded', 'aria-modal'],\n superclassRole: ['window'],\n accessibleNameRequired: true\n },\n directory: {\n type: 'structure',\n deprecated: true,\n // Spec difference: Aria-expanded removed in 1.2\n allowedAttrs: ['aria-expanded'],\n superclassRole: ['list'],\n // Note: spec difference\n nameFromContent: true\n },\n document: {\n type: 'structure',\n // Spec difference: Aria-expanded removed in 1.2\n allowedAttrs: ['aria-expanded'],\n superclassRole: ['structure']\n },\n emphasis: {\n type: 'structure',\n superclassRole: ['section'],\n prohibitedAttrs: ['aria-label', 'aria-labelledby']\n },\n feed: {\n type: 'structure',\n requiredOwned: ['article'],\n // Spec difference: Aria-expanded removed in 1.2\n allowedAttrs: ['aria-expanded'],\n superclassRole: ['list']\n },\n figure: {\n type: 'structure',\n // Spec difference: Aria-expanded removed in 1.2\n allowedAttrs: ['aria-expanded'],\n superclassRole: ['section'],\n // Note: spec difference\n nameFromContent: true\n },\n form: {\n type: 'landmark',\n // Spec difference: Aria-expanded removed in 1.2\n allowedAttrs: ['aria-expanded'],\n superclassRole: ['landmark']\n },\n grid: {\n type: 'composite',\n requiredOwned: ['rowgroup', 'row'],\n // Spec difference: Aria-expanded removed in 1.2\n allowedAttrs: [\n 'aria-level',\n 'aria-multiselectable',\n 'aria-readonly',\n 'aria-activedescendant',\n 'aria-colcount',\n 'aria-expanded',\n 'aria-rowcount'\n ],\n superclassRole: ['composite', 'table'],\n // Note: spec difference\n accessibleNameRequired: false\n },\n gridcell: {\n type: 'widget',\n requiredContext: ['row'],\n allowedAttrs: [\n 'aria-readonly',\n 'aria-required',\n 'aria-selected',\n 'aria-colindex',\n 'aria-colspan',\n 'aria-expanded',\n 'aria-rowindex',\n 'aria-rowspan'\n ],\n superclassRole: ['cell', 'widget'],\n nameFromContent: true\n },\n group: {\n type: 'structure',\n // Spec difference: Aria-expanded removed in 1.2\n allowedAttrs: ['aria-activedescendant', 'aria-expanded'],\n superclassRole: ['section']\n },\n heading: {\n type: 'structure',\n requiredAttrs: ['aria-level'],\n // Spec difference: Aria-expanded removed in 1.2\n allowedAttrs: ['aria-expanded'],\n superclassRole: ['sectionhead'],\n // Note: spec difference\n accessibleNameRequired: false,\n nameFromContent: true\n },\n img: {\n type: 'structure',\n // Spec difference: Aria-expanded removed in 1.2\n allowedAttrs: ['aria-expanded'],\n superclassRole: ['section'],\n accessibleNameRequired: true,\n childrenPresentational: true\n },\n input: {\n type: 'abstract',\n superclassRole: ['widget']\n },\n insertion: {\n type: 'structure',\n superclassRole: ['section'],\n prohibitedAttrs: ['aria-label', 'aria-labelledby']\n },\n landmark: {\n type: 'abstract',\n superclassRole: ['section']\n },\n link: {\n type: 'widget',\n allowedAttrs: ['aria-expanded'],\n superclassRole: ['command'],\n accessibleNameRequired: true,\n nameFromContent: true\n },\n list: {\n type: 'structure',\n requiredOwned: ['listitem'],\n // Spec difference: Aria-expanded removed in 1.2\n allowedAttrs: ['aria-expanded'],\n superclassRole: ['section']\n },\n listbox: {\n // Note: spec difference\n type: 'widget',\n requiredOwned: ['group', 'option'],\n allowedAttrs: [\n 'aria-multiselectable',\n 'aria-readonly',\n 'aria-required',\n 'aria-activedescendant',\n 'aria-expanded',\n 'aria-orientation'\n ],\n superclassRole: ['select'],\n accessibleNameRequired: true\n },\n listitem: {\n type: 'structure',\n requiredContext: ['list'],\n allowedAttrs: [\n 'aria-level',\n 'aria-posinset',\n 'aria-setsize',\n 'aria-expanded'\n ],\n superclassRole: ['section'],\n // Note: spec difference\n nameFromContent: true\n },\n log: {\n type: 'structure',\n // Spec difference: Aria-expanded removed in 1.2\n allowedAttrs: ['aria-expanded'],\n superclassRole: ['section']\n },\n main: {\n type: 'landmark',\n // Spec difference: Aria-expanded removed in 1.2\n allowedAttrs: ['aria-expanded'],\n superclassRole: ['landmark']\n },\n marquee: {\n type: 'structure',\n // Spec difference: Aria-expanded removed in 1.2\n allowedAttrs: ['aria-expanded'],\n superclassRole: ['section']\n },\n math: {\n type: 'structure',\n // Spec difference: Aria-expanded removed in 1.2\n allowedAttrs: ['aria-expanded'],\n superclassRole: ['section'],\n childrenPresentational: true\n },\n menu: {\n type: 'composite',\n // Note: spec difference (menu & separator as required owned)\n requiredOwned: [\n 'group',\n 'menuitemradio',\n 'menuitem',\n 'menuitemcheckbox',\n 'menu',\n 'separator'\n ],\n // Spec difference: Aria-expanded removed in 1.2\n allowedAttrs: [\n 'aria-activedescendant',\n 'aria-expanded',\n 'aria-orientation'\n ],\n superclassRole: ['select']\n },\n menubar: {\n type: 'composite',\n // Note: spec difference (menu & separator as required owned)\n requiredOwned: [\n 'group',\n 'menuitemradio',\n 'menuitem',\n 'menuitemcheckbox',\n 'menu',\n 'separator'\n ],\n // Spec difference: Aria-expanded removed in 1.2\n allowedAttrs: [\n 'aria-activedescendant',\n 'aria-expanded',\n 'aria-orientation'\n ],\n superclassRole: ['menu']\n },\n menuitem: {\n type: 'widget',\n requiredContext: ['menu', 'menubar', 'group'],\n // Note: aria-expanded is not in the 1.1 spec but is\n // consistently supported in ATs and was added in 1.2\n allowedAttrs: ['aria-posinset', 'aria-setsize', 'aria-expanded'],\n superclassRole: ['command'],\n accessibleNameRequired: true,\n nameFromContent: true\n },\n menuitemcheckbox: {\n type: 'widget',\n requiredContext: ['menu', 'menubar', 'group'],\n requiredAttrs: ['aria-checked'],\n allowedAttrs: [\n 'aria-expanded',\n 'aria-posinset',\n 'aria-readonly',\n 'aria-setsize'\n ],\n superclassRole: ['checkbox', 'menuitem'],\n accessibleNameRequired: true,\n nameFromContent: true,\n childrenPresentational: true\n },\n menuitemradio: {\n type: 'widget',\n requiredContext: ['menu', 'menubar', 'group'],\n requiredAttrs: ['aria-checked'],\n allowedAttrs: [\n 'aria-expanded',\n 'aria-posinset',\n 'aria-readonly',\n 'aria-setsize'\n ],\n superclassRole: ['menuitemcheckbox', 'radio'],\n accessibleNameRequired: true,\n nameFromContent: true,\n childrenPresentational: true\n },\n meter: {\n type: 'structure',\n requiredAttrs: ['aria-valuenow'],\n allowedAttrs: ['aria-valuemax', 'aria-valuemin', 'aria-valuetext'],\n superclassRole: ['range'],\n accessibleNameRequired: true,\n childrenPresentational: true\n },\n mark: {\n type: 'structure',\n superclassRole: ['section'],\n prohibitedAttrs: ['aria-label', 'aria-labelledby']\n },\n navigation: {\n type: 'landmark',\n // Spec difference: Aria-expanded removed in 1.2\n allowedAttrs: ['aria-expanded'],\n superclassRole: ['landmark']\n },\n none: {\n type: 'structure',\n superclassRole: ['structure'],\n prohibitedAttrs: ['aria-label', 'aria-labelledby']\n },\n note: {\n type: 'structure',\n // Spec difference: Aria-expanded removed in 1.2\n allowedAttrs: ['aria-expanded'],\n superclassRole: ['section']\n },\n option: {\n type: 'widget',\n requiredContext: ['group', 'listbox'],\n // Note: since the option role has an implicit\n // aria-selected value it is not required to be added by\n // the user\n allowedAttrs: [\n 'aria-selected',\n 'aria-checked',\n 'aria-posinset',\n 'aria-setsize'\n ],\n superclassRole: ['input'],\n accessibleNameRequired: true,\n nameFromContent: true,\n childrenPresentational: true\n },\n paragraph: {\n type: 'structure',\n superclassRole: ['section'],\n prohibitedAttrs: ['aria-label', 'aria-labelledby']\n },\n presentation: {\n type: 'structure',\n superclassRole: ['structure'],\n prohibitedAttrs: ['aria-label', 'aria-labelledby']\n },\n progressbar: {\n type: 'widget',\n // Spec difference: Aria-expanded removed in 1.2\n allowedAttrs: [\n 'aria-expanded',\n 'aria-valuemax',\n 'aria-valuemin',\n 'aria-valuenow',\n 'aria-valuetext'\n ],\n superclassRole: ['range'],\n accessibleNameRequired: true,\n childrenPresentational: true\n },\n radio: {\n type: 'widget',\n // Note: aria-required is not in the 1.1 or 1.2 specs but is\n // consistently supported in ATs on the individual radio element\n requiredAttrs: ['aria-checked'],\n allowedAttrs: ['aria-posinset', 'aria-setsize', 'aria-required'],\n superclassRole: ['input'],\n accessibleNameRequired: true,\n nameFromContent: true,\n childrenPresentational: true\n },\n radiogroup: {\n type: 'composite',\n // Note: spec difference (no required owned)\n // Spec difference: Aria-expanded removed in 1.2\n allowedAttrs: [\n 'aria-readonly',\n 'aria-required',\n 'aria-activedescendant',\n 'aria-expanded',\n 'aria-orientation'\n ],\n superclassRole: ['select'],\n // Note: spec difference\n accessibleNameRequired: false\n },\n range: {\n type: 'abstract',\n superclassRole: ['widget']\n },\n region: {\n type: 'landmark',\n // Spec difference: Aria-expanded removed in 1.2\n allowedAttrs: ['aria-expanded'],\n superclassRole: ['landmark'],\n // Note: spec difference\n accessibleNameRequired: false\n },\n roletype: {\n type: 'abstract',\n superclassRole: []\n },\n row: {\n type: 'structure',\n requiredContext: ['grid', 'rowgroup', 'table', 'treegrid'],\n requiredOwned: ['cell', 'columnheader', 'gridcell', 'rowheader'],\n allowedAttrs: [\n 'aria-colindex',\n 'aria-level',\n 'aria-rowindex',\n 'aria-selected',\n 'aria-activedescendant',\n 'aria-expanded',\n 'aria-posinset',\n 'aria-setsize'\n ],\n superclassRole: ['group', 'widget'],\n nameFromContent: true\n },\n rowgroup: {\n type: 'structure',\n requiredContext: ['grid', 'table', 'treegrid'],\n requiredOwned: ['row'],\n superclassRole: ['structure'],\n nameFromContent: true\n },\n rowheader: {\n type: 'structure',\n requiredContext: ['row'],\n // Spec difference: Aria-expanded removed in 1.2\n allowedAttrs: [\n 'aria-sort',\n 'aria-colindex',\n 'aria-colspan',\n 'aria-expanded',\n 'aria-readonly',\n 'aria-required',\n 'aria-rowindex',\n 'aria-rowspan',\n 'aria-selected'\n ],\n superclassRole: ['cell', 'gridcell', 'sectionhead'],\n // Note: spec difference\n accessibleNameRequired: false,\n nameFromContent: true\n },\n scrollbar: {\n type: 'widget',\n requiredAttrs: ['aria-valuenow'],\n // Note: since the scrollbar role has implicit\n // aria-orientation, aria-valuemax, aria-valuemin values it\n // is not required to be added by the user\n //\n // Note: because aria-controls is not well supported we will not\n // make it a required attribute even though it is required in the\n // spec\n allowedAttrs: [\n 'aria-controls',\n 'aria-orientation',\n 'aria-valuemax',\n 'aria-valuemin',\n 'aria-valuetext'\n ],\n superclassRole: ['range'],\n childrenPresentational: true\n },\n search: {\n type: 'landmark',\n // Spec difference: Aria-expanded removed in 1.2\n allowedAttrs: ['aria-expanded'],\n superclassRole: ['landmark']\n },\n searchbox: {\n type: 'widget',\n allowedAttrs: [\n 'aria-activedescendant',\n 'aria-autocomplete',\n 'aria-multiline',\n 'aria-placeholder',\n 'aria-readonly',\n 'aria-required'\n ],\n superclassRole: ['textbox'],\n accessibleNameRequired: true\n },\n section: {\n type: 'abstract',\n superclassRole: ['structure'],\n // Note: spec difference\n nameFromContent: true\n },\n sectionhead: {\n type: 'abstract',\n superclassRole: ['structure'],\n // Note: spec difference\n nameFromContent: true\n },\n select: {\n type: 'abstract',\n superclassRole: ['composite', 'group']\n },\n separator: {\n type: 'structure',\n requiredAttrs: ['aria-valuenow'],\n // Note: since the separator role has implicit\n // aria-orientation, aria-valuemax, aria-valuemin, and\n // values it is not required to be added by\n // the user\n allowedAttrs: [\n 'aria-valuemax',\n 'aria-valuemin',\n 'aria-orientation',\n 'aria-valuetext'\n ],\n superclassRole: ['structure', 'widget'],\n childrenPresentational: true\n },\n slider: {\n type: 'widget',\n requiredAttrs: ['aria-valuenow'],\n // Note: since the slider role has implicit\n // aria-orientation, aria-valuemax, aria-valuemin values it\n // is not required to be added by the user\n // Note: aria-required is not in the 1.1 or 1.2 specs but is\n // consistently supported in ATs\n allowedAttrs: [\n 'aria-valuemax',\n 'aria-valuemin',\n 'aria-orientation',\n 'aria-readonly',\n 'aria-required',\n 'aria-valuetext'\n ],\n superclassRole: ['input', 'range'],\n accessibleNameRequired: true,\n childrenPresentational: true\n },\n spinbutton: {\n type: 'widget',\n // Note: since the spinbutton role has implicit\n // aria-valuenow, aria-valuemax, aria-valuemin values it\n // is not required to be added by the user\n allowedAttrs: [\n 'aria-valuemax',\n 'aria-valuemin',\n 'aria-readonly',\n 'aria-required',\n 'aria-activedescendant',\n 'aria-valuetext',\n 'aria-valuenow'\n ],\n superclassRole: ['composite', 'input', 'range'],\n accessibleNameRequired: true\n },\n status: {\n type: 'structure',\n // Spec difference: Aria-expanded removed in 1.2\n allowedAttrs: ['aria-expanded'],\n superclassRole: ['section']\n },\n strong: {\n type: 'structure',\n superclassRole: ['section'],\n prohibitedAttrs: ['aria-label', 'aria-labelledby']\n },\n structure: {\n type: 'abstract',\n superclassRole: ['roletype']\n },\n subscript: {\n type: 'structure',\n superclassRole: ['section'],\n prohibitedAttrs: ['aria-label', 'aria-labelledby']\n },\n superscript: {\n type: 'structure',\n superclassRole: ['section'],\n prohibitedAttrs: ['aria-label', 'aria-labelledby']\n },\n switch: {\n type: 'widget',\n requiredAttrs: ['aria-checked'],\n allowedAttrs: ['aria-expanded', 'aria-readonly', 'aria-required'],\n superclassRole: ['checkbox'],\n accessibleNameRequired: true,\n nameFromContent: true,\n childrenPresentational: true\n },\n suggestion: {\n type: 'structure',\n requiredOwned: ['insertion', 'deletion'],\n superclassRole: ['section'],\n prohibitedAttrs: ['aria-label', 'aria-labelledby']\n },\n tab: {\n type: 'widget',\n requiredContext: ['tablist'],\n // Spec difference: Aria-expanded removed in 1.2\n allowedAttrs: [\n 'aria-posinset',\n 'aria-selected',\n 'aria-setsize',\n 'aria-expanded'\n ],\n superclassRole: ['sectionhead', 'widget'],\n nameFromContent: true,\n childrenPresentational: true\n },\n table: {\n type: 'structure',\n requiredOwned: ['rowgroup', 'row'],\n // Spec difference: Aria-expanded removed in 1.2\n allowedAttrs: ['aria-colcount', 'aria-rowcount', 'aria-expanded'],\n // NOTE: although the spec says this is not named from contents,\n // the accessible text acceptance tests (#139 and #140) require\n // table be named from content (we even had to special case\n // table in commons/aria/named-from-contents)\n superclassRole: ['section'],\n // Note: spec difference\n accessibleNameRequired: false,\n nameFromContent: true\n },\n tablist: {\n type: 'composite',\n requiredOwned: ['tab'],\n // NOTE: aria-expanded is from the 1.0 spec but is still\n // consistently supported in ATs\n allowedAttrs: [\n 'aria-level',\n 'aria-multiselectable',\n 'aria-orientation',\n 'aria-activedescendant',\n 'aria-expanded'\n ],\n superclassRole: ['composite']\n },\n tabpanel: {\n // Spec ambiguity: Aria 1.1 and 1.2 both say that tabpanel rolls up to\n // structure via its section superclass, but also include it as a widget\n // in §5.3.2 Widget Roles.\n type: 'structure',\n // Spec difference: Aria-expanded removed in 1.2\n allowedAttrs: ['aria-expanded'],\n superclassRole: ['section'],\n // Note: spec difference\n accessibleNameRequired: false\n },\n term: {\n type: 'structure',\n // Spec difference: Aria-expanded removed in 1.2\n allowedAttrs: ['aria-expanded'],\n superclassRole: ['section'],\n // Note: spec difference\n nameFromContent: true\n },\n text: {\n type: 'structure',\n superclassRole: ['section'],\n nameFromContent: true\n },\n textbox: {\n type: 'widget',\n allowedAttrs: [\n 'aria-activedescendant',\n 'aria-autocomplete',\n 'aria-multiline',\n 'aria-placeholder',\n 'aria-readonly',\n 'aria-required'\n ],\n superclassRole: ['input'],\n accessibleNameRequired: true\n },\n time: {\n type: 'structure',\n superclassRole: ['section']\n },\n timer: {\n type: 'structure',\n // Spec difference: Aria-expanded removed in 1.2\n allowedAttrs: ['aria-expanded'],\n superclassRole: ['status']\n },\n toolbar: {\n type: 'structure',\n // Spec difference: Aria-expanded removed in 1.2\n allowedAttrs: [\n 'aria-orientation',\n 'aria-activedescendant',\n 'aria-expanded'\n ],\n superclassRole: ['group'],\n accessibleNameRequired: true\n },\n tooltip: {\n type: 'structure',\n // Spec difference: Aria-expanded removed in 1.2\n allowedAttrs: ['aria-expanded'],\n superclassRole: ['section'],\n nameFromContent: true\n },\n tree: {\n type: 'composite',\n requiredOwned: ['group', 'treeitem'],\n // Spec difference: Aria-expanded removed in 1.2\n allowedAttrs: [\n 'aria-multiselectable',\n 'aria-required',\n 'aria-activedescendant',\n 'aria-expanded',\n 'aria-orientation'\n ],\n superclassRole: ['select'],\n // Note: spec difference\n accessibleNameRequired: false\n },\n treegrid: {\n type: 'composite',\n requiredOwned: ['rowgroup', 'row'],\n // Spec difference: Aria-expanded removed in 1.2\n allowedAttrs: [\n 'aria-activedescendant',\n 'aria-colcount',\n 'aria-expanded',\n 'aria-level',\n 'aria-multiselectable',\n 'aria-orientation',\n 'aria-readonly',\n 'aria-required',\n 'aria-rowcount'\n ],\n superclassRole: ['grid', 'tree'],\n // Note: spec difference\n accessibleNameRequired: false\n },\n treeitem: {\n type: 'widget',\n requiredContext: ['group', 'tree'],\n allowedAttrs: [\n 'aria-checked',\n 'aria-expanded',\n 'aria-level',\n 'aria-posinset',\n 'aria-selected',\n 'aria-setsize'\n ],\n superclassRole: ['listitem', 'option'],\n accessibleNameRequired: true,\n nameFromContent: true\n },\n widget: {\n type: 'abstract',\n superclassRole: ['roletype']\n },\n window: {\n type: 'abstract',\n superclassRole: ['roletype']\n }\n};\n\n// Source https://www.w3.org/TR/dpub-aria-1.0/\nconst dpubRoles: Record<string, any> = {\n 'doc-abstract': {\n type: 'section',\n allowedAttrs: ['aria-expanded'],\n superclassRole: ['section']\n },\n 'doc-acknowledgments': {\n type: 'landmark',\n allowedAttrs: ['aria-expanded'],\n superclassRole: ['landmark']\n },\n 'doc-afterword': {\n type: 'landmark',\n allowedAttrs: ['aria-expanded'],\n superclassRole: ['landmark']\n },\n 'doc-appendix': {\n type: 'landmark',\n allowedAttrs: ['aria-expanded'],\n superclassRole: ['landmark']\n },\n 'doc-backlink': {\n type: 'link',\n allowedAttrs: ['aria-expanded'],\n nameFromContent: true,\n superclassRole: ['link']\n },\n 'doc-biblioentry': {\n type: 'listitem',\n allowedAttrs: [\n 'aria-expanded',\n 'aria-level',\n 'aria-posinset',\n 'aria-setsize'\n ],\n superclassRole: ['listitem'],\n deprecated: true\n },\n 'doc-bibliography': {\n type: 'landmark',\n allowedAttrs: ['aria-expanded'],\n superclassRole: ['landmark']\n },\n 'doc-biblioref': {\n type: 'link',\n allowedAttrs: ['aria-expanded'],\n nameFromContent: true,\n superclassRole: ['link']\n },\n 'doc-chapter': {\n type: 'landmark',\n allowedAttrs: ['aria-expanded'],\n superclassRole: ['landmark']\n },\n 'doc-colophon': {\n type: 'section',\n allowedAttrs: ['aria-expanded'],\n superclassRole: ['section']\n },\n 'doc-conclusion': {\n type: 'landmark',\n allowedAttrs: ['aria-expanded'],\n superclassRole: ['landmark']\n },\n 'doc-cover': {\n type: 'img',\n allowedAttrs: ['aria-expanded'],\n superclassRole: ['img']\n },\n 'doc-credit': {\n type: 'section',\n allowedAttrs: ['aria-expanded'],\n superclassRole: ['section']\n },\n 'doc-credits': {\n type: 'landmark',\n allowedAttrs: ['aria-expanded'],\n superclassRole: ['landmark']\n },\n 'doc-dedication': {\n type: 'section',\n allowedAttrs: ['aria-expanded'],\n superclassRole: ['section']\n },\n 'doc-endnote': {\n type: 'listitem',\n allowedAttrs: [\n 'aria-expanded',\n 'aria-level',\n 'aria-posinset',\n 'aria-setsize'\n ],\n superclassRole: ['listitem'],\n deprecated: true\n },\n 'doc-endnotes': {\n type: 'landmark',\n allowedAttrs: ['aria-expanded'],\n superclassRole: ['landmark']\n },\n 'doc-epigraph': {\n type: 'section',\n allowedAttrs: ['aria-expanded'],\n superclassRole: ['section']\n },\n 'doc-epilogue': {\n type: 'landmark',\n allowedAttrs: ['aria-expanded'],\n superclassRole: ['landmark']\n },\n 'doc-errata': {\n type: 'landmark',\n allowedAttrs: ['aria-expanded'],\n superclassRole: ['landmark']\n },\n 'doc-example': {\n type: 'section',\n allowedAttrs: ['aria-expanded'],\n superclassRole: ['section']\n },\n 'doc-footnote': {\n type: 'section',\n allowedAttrs: ['aria-expanded'],\n superclassRole: ['section']\n },\n 'doc-foreword': {\n type: 'landmark',\n allowedAttrs: ['aria-expanded'],\n superclassRole: ['landmark']\n },\n 'doc-glossary': {\n type: 'landmark',\n allowedAttrs: ['aria-expanded'],\n superclassRole: ['landmark']\n },\n 'doc-glossref': {\n type: 'link',\n allowedAttrs: ['aria-expanded'],\n nameFromContent: true,\n superclassRole: ['link']\n },\n 'doc-index': {\n type: 'navigation',\n allowedAttrs: ['aria-expanded'],\n superclassRole: ['navigation']\n },\n 'doc-introduction': {\n type: 'landmark',\n allowedAttrs: ['aria-expanded'],\n superclassRole: ['landmark']\n },\n 'doc-noteref': {\n type: 'link',\n allowedAttrs: ['aria-expanded'],\n nameFromContent: true,\n superclassRole: ['link']\n },\n 'doc-notice': {\n type: 'note',\n allowedAttrs: ['aria-expanded'],\n superclassRole: ['note']\n },\n 'doc-pagebreak': {\n type: 'separator',\n allowedAttrs: ['aria-expanded', 'aria-orientation'],\n superclassRole: ['separator'],\n childrenPresentational: true\n },\n 'doc-pagelist': {\n type: 'navigation',\n allowedAttrs: ['aria-expanded'],\n superclassRole: ['navigation']\n },\n 'doc-part': {\n type: 'landmark',\n allowedAttrs: ['aria-expanded'],\n superclassRole: ['landmark']\n },\n 'doc-preface': {\n type: 'landmark',\n allowedAttrs: ['aria-expanded'],\n superclassRole: ['landmark']\n },\n 'doc-prologue': {\n type: 'landmark',\n allowedAttrs: ['aria-expanded'],\n superclassRole: ['landmark']\n },\n 'doc-pullquote': {\n type: 'none',\n superclassRole: ['none']\n },\n 'doc-qna': {\n type: 'section',\n allowedAttrs: ['aria-expanded'],\n superclassRole: ['section']\n },\n 'doc-subtitle': {\n type: 'sectionhead',\n allowedAttrs: ['aria-expanded'],\n superclassRole: ['sectionhead']\n },\n 'doc-tip': {\n type: 'note',\n allowedAttrs: ['aria-expanded'],\n superclassRole: ['note']\n },\n 'doc-toc': {\n type: 'navigation',\n allowedAttrs: ['aria-expanded'],\n superclassRole: ['navigation']\n }\n};\nexport { dpubRoles };\n\n// Source: https://www.w3.org/TR/graphics-aria-1.0/\n\nconst graphicsRoles: Record<string, any> = {\n 'graphics-document': {\n type: 'structure',\n superclassRole: ['document'],\n accessibleNameRequired: true\n },\n 'graphics-object': {\n type: 'structure',\n superclassRole: ['group'],\n nameFromContent: true\n },\n 'graphics-symbol': {\n type: 'structure',\n superclassRole: ['img'],\n accessibleNameRequired: true,\n childrenPresentational: true\n }\n};\nexport { graphicsRoles };\n\n// Source: https://www.w3.org/TR/html-aria/#allowed-aria-roles-states-and-properties\n// Source: https://www.w3.org/TR/html-aam-1.0/#html-element-role-mappings\n// Source https://html.spec.whatwg.org/multipage/dom.html#content-models\n// Source https://dom.spec.whatwg.org/#dom-element-attachshadow\nconst htmlElms: Record<string, any> = {\n a: {\n // Note: variants work by matching the node against the\n // `matches` attribute. if the variant matches AND has the\n // desired property (contentTypes, etc.) then we use it,\n // otherwise we move on to the next matching variant\n variant: {\n href: {\n matches: '[href]',\n contentTypes: ['interactive', 'phrasing', 'flow'],\n allowedRoles: [\n 'button',\n 'checkbox',\n 'menuitem',\n 'menuitemcheckbox',\n 'menuitemradio',\n 'option',\n 'radio',\n 'switch',\n 'tab',\n 'treeitem',\n 'doc-backlink',\n 'doc-biblioref',\n 'doc-glossref',\n 'doc-noteref'\n ],\n namingMethods: ['subtreeText']\n },\n // Note: the default variant is a special variant and is\n // used as the last match if none of the other variants\n // match or have the desired attribute\n default: {\n contentTypes: ['phrasing', 'flow'],\n allowedRoles: true\n }\n }\n },\n abbr: {\n contentTypes: ['phrasing', 'flow'],\n allowedRoles: true\n },\n address: {\n contentTypes: ['flow'],\n allowedRoles: true\n },\n area: {\n variant: {\n href: {\n matches: '[href]',\n allowedRoles: false\n },\n default: {\n allowedRoles: ['button', 'link']\n }\n },\n contentTypes: ['phrasing', 'flow'],\n namingMethods: ['altText']\n },\n article: {\n contentTypes: ['sectioning', 'flow'],\n allowedRoles: [\n 'feed',\n 'presentation',\n 'none',\n 'document',\n 'application',\n 'main',\n 'region'\n ],\n shadowRoot: true\n },\n aside: {\n contentTypes: ['sectioning', 'flow'],\n allowedRoles: [\n 'feed',\n 'note',\n 'presentation',\n 'none',\n 'region',\n 'search',\n 'doc-dedication',\n 'doc-example',\n 'doc-footnote',\n 'doc-glossary',\n 'doc-pullquote',\n 'doc-tip'\n ]\n },\n audio: {\n variant: {\n controls: {\n matches: '[controls]',\n contentTypes: ['interactive', 'embedded', 'phrasing', 'flow']\n },\n default: {\n contentTypes: ['embedded', 'phrasing', 'flow']\n }\n },\n // Note: if the property applies regardless of variants it is\n // placed at the top level instead of the default variant\n allowedRoles: ['application'],\n chromiumRole: 'Audio'\n },\n b: {\n contentTypes: ['phrasing', 'flow'],\n allowedRoles: true\n },\n base: {\n allowedRoles: false,\n noAriaAttrs: true\n },\n bdi: {\n contentTypes: ['phrasing', 'flow'],\n allowedRoles: true\n },\n bdo: {\n contentTypes: ['phrasing', 'flow'],\n allowedRoles: true\n },\n blockquote: {\n contentTypes: ['flow'],\n allowedRoles: true,\n shadowRoot: true\n },\n body: {\n allowedRoles: false,\n shadowRoot: true\n },\n br: {\n contentTypes: ['phrasing', 'flow'],\n allowedRoles: ['presentation', 'none'],\n namingMethods: ['titleText', 'singleSpace'],\n allowedAriaAttrs: ['aria-hidden']\n },\n button: {\n contentTypes: ['interactive', 'phrasing', 'flow'],\n allowedRoles: [\n 'checkbox',\n 'combobox',\n 'gridcell',\n 'link',\n 'menuitem',\n 'menuitemcheckbox',\n 'menuitemradio',\n 'option',\n 'radio',\n 'separator',\n 'slider',\n 'switch',\n 'tab',\n 'treeitem'\n ],\n // 5.4 button Element\n namingMethods: ['subtreeText']\n },\n canvas: {\n allowedRoles: true,\n contentTypes: ['embedded', 'phrasing', 'flow'],\n chromiumRole: 'Canvas'\n },\n caption: {\n allowedRoles: false\n },\n cite: {\n contentTypes: ['phrasing', 'flow'],\n allowedRoles: true\n },\n code: {\n contentTypes: ['phrasing', 'flow'],\n allowedRoles: true\n },\n col: {\n allowedRoles: false,\n noAriaAttrs: true\n },\n colgroup: {\n allowedRoles: false,\n noAriaAttrs: true\n },\n data: {\n contentTypes: ['phrasing', 'flow'],\n allowedRoles: true\n },\n datalist: {\n contentTypes: ['phrasing', 'flow'],\n allowedRoles: false,\n noAriaAttrs: true,\n implicitAttrs: {\n // Note: even though the value of aria-multiselectable is based\n // on the attributes, we don't currently need to know the\n // precise value. however, this allows us to make the attribute\n // future proof in case we ever do need to know it\n 'aria-multiselectable': 'false'\n }\n },\n dd: {\n allowedRoles: false\n },\n del: {\n contentTypes: ['phrasing', 'flow'],\n allowedRoles: true\n },\n dfn: {\n contentTypes: ['phrasing', 'flow'],\n allowedRoles: true\n },\n details: {\n contentTypes: ['interactive', 'flow'],\n allowedRoles: false\n },\n dialog: {\n contentTypes: ['flow'],\n allowedRoles: ['alertdialog']\n },\n div: {\n contentTypes: ['flow'],\n allowedRoles: true,\n shadowRoot: true\n },\n dl: {\n contentTypes: ['flow'],\n allowedRoles: ['group', 'list', 'presentation', 'none'],\n chromiumRole: 'DescriptionList'\n },\n dt: {\n allowedRoles: ['listitem']\n },\n em: {\n contentTypes: ['phrasing', 'flow'],\n allowedRoles: true\n },\n embed: {\n contentTypes: ['interactive', 'embedded', 'phrasing', 'flow'],\n allowedRoles: ['application', 'document', 'img', 'presentation', 'none'],\n chromiumRole: 'EmbeddedObject'\n },\n fieldset: {\n contentTypes: ['flow'],\n allowedRoles: ['none', 'presentation', 'radiogroup'],\n // 5.5 fieldset and legend Elements\n namingMethods: ['fieldsetLegendText']\n },\n figcaption: {\n allowedRoles: ['group', 'none', 'presentation']\n },\n figure: {\n contentTypes: ['flow'],\n // Note: technically you're allowed no role when a figcaption\n // descendant, but we can't match that so we'll go with any role\n allowedRoles: true,\n // 5.9 figure and figcaption Elements\n namingMethods: ['figureText', 'titleText']\n },\n footer: {\n contentTypes: ['flow'],\n allowedRoles: ['group', 'none', 'presentation', 'doc-footnote'],\n shadowRoot: true\n },\n form: {\n contentTypes: ['flow'],\n allowedRoles: ['form', 'search', 'none', 'presentation']\n },\n h1: {\n contentTypes: ['heading', 'flow'],\n allowedRoles: ['none', 'presentation', 'tab', 'doc-subtitle'],\n shadowRoot: true,\n implicitAttrs: {\n 'aria-level': '1'\n }\n },\n h2: {\n contentTypes: ['heading', 'flow'],\n allowedRoles: ['none', 'presentation', 'tab', 'doc-subtitle'],\n shadowRoot: true,\n implicitAttrs: {\n 'aria-level': '2'\n }\n },\n h3: {\n contentTypes: ['heading', 'flow'],\n allowedRoles: ['none', 'presentation', 'tab', 'doc-subtitle'],\n shadowRoot: true,\n implicitAttrs: {\n 'aria-level': '3'\n }\n },\n h4: {\n contentTypes: ['heading', 'flow'],\n allowedRoles: ['none', 'presentation', 'tab', 'doc-subtitle'],\n shadowRoot: true,\n implicitAttrs: {\n 'aria-level': '4'\n }\n },\n h5: {\n contentTypes: ['heading', 'flow'],\n allowedRoles: ['none', 'presentation', 'tab', 'doc-subtitle'],\n shadowRoot: true,\n implicitAttrs: {\n 'aria-level': '5'\n }\n },\n h6: {\n contentTypes: ['heading', 'flow'],\n allowedRoles: ['none', 'presentation', 'tab', 'doc-subtitle'],\n shadowRoot: true,\n implicitAttrs: {\n 'aria-level': '6'\n }\n },\n head: {\n allowedRoles: false,\n noAriaAttrs: true\n },\n header: {\n contentTypes: ['flow'],\n allowedRoles: ['group', 'none', 'presentation', 'doc-footnote'],\n shadowRoot: true\n },\n hgroup: {\n contentTypes: ['heading', 'flow'],\n allowedRoles: true\n },\n hr: {\n contentTypes: ['flow'],\n allowedRoles: ['none', 'presentation', 'doc-pagebreak'],\n namingMethods: ['titleText', 'singleSpace']\n },\n html: {\n allowedRoles: false,\n noAriaAttrs: true\n },\n i: {\n contentTypes: ['phrasing', 'flow'],\n allowedRoles: true\n },\n iframe: {\n contentTypes: ['interactive', 'embedded', 'phrasing', 'flow'],\n allowedRoles: ['application', 'document', 'img', 'none', 'presentation'],\n chromiumRole: 'Iframe'\n },\n img: {\n variant: {\n nonEmptyAlt: {\n matches: [\n {\n // Because <img role=\"none\" alt=\"foo\" /> has no accessible name:\n attributes: {\n alt: '/.+/'\n }\n },\n {\n hasAccessibleName: true\n }\n ],\n allowedRoles: [\n 'button',\n 'checkbox',\n 'link',\n 'math',\n 'menuitem',\n 'menuitemcheckbox',\n 'menuitemradio',\n 'meter',\n 'option',\n 'progressbar',\n 'radio',\n 'scrollbar',\n 'separator',\n 'slider',\n 'switch',\n 'tab',\n 'treeitem',\n 'doc-cover'\n ]\n },\n usemap: {\n matches: '[usemap]',\n contentTypes: ['interactive', 'embedded', 'flow']\n },\n default: {\n // Note: allow role presentation and none on image with no\n // alt as a way to prevent axe from flagging the image as\n // needing an alt\n allowedRoles: ['presentation', 'none'],\n // Note: spec change (do not count as phrasing), because browsers\n // insert a space between an img's accessible name and other\n // elements' accessible names\n contentTypes: ['embedded', 'flow']\n }\n },\n // 5.10 img Element\n namingMethods: ['altText']\n },\n input: {\n variant: {\n button: {\n matches: {\n properties: {\n type: 'button'\n }\n },\n allowedRoles: [\n 'checkbox',\n 'combobox',\n 'link',\n 'menuitem',\n 'menuitemcheckbox',\n 'menuitemradio',\n 'option',\n 'radio',\n 'switch',\n 'tab'\n ]\n },\n // 5.2 input type=\"button\", input type=\"submit\" and input type=\"reset\"\n buttonType: {\n matches: {\n properties: {\n type: ['button', 'submit', 'reset']\n }\n },\n namingMethods: ['valueText', 'titleText', 'buttonDefaultText']\n },\n checkboxPressed: {\n matches: {\n properties: {\n type: 'checkbox'\n },\n attributes: {\n 'aria-pressed': '/.*/'\n }\n },\n allowedRoles: ['button', 'menuitemcheckbox', 'option', 'switch'],\n implicitAttrs: {\n 'aria-checked': 'false'\n }\n },\n checkbox: {\n matches: {\n properties: {\n type: 'checkbox'\n },\n attributes: {\n 'aria-pressed': null\n }\n },\n allowedRoles: ['menuitemcheckbox', 'option', 'switch'],\n implicitAttrs: {\n 'aria-checked': 'false'\n }\n },\n noRoles: {\n matches: {\n properties: {\n // Note: types of url, search, tel, and email are listed\n // as not allowed roles however since they are text\n // types they should be allowed to have role=combobox\n type: [\n 'color',\n 'date',\n 'datetime-local',\n 'file',\n 'month',\n 'number',\n 'password',\n 'range',\n 'reset',\n 'submit',\n 'time',\n 'week'\n ]\n }\n },\n allowedRoles: false\n },\n hidden: {\n matches: {\n properties: {\n type: 'hidden'\n }\n },\n // Note: spec change (do not count as phrasing)\n contentTypes: ['flow'],\n allowedRoles: false,\n noAriaAttrs: true\n },\n image: {\n matches: {\n properties: {\n type: 'image'\n }\n },\n allowedRoles: [\n 'link',\n 'menuitem',\n 'menuitemcheckbox',\n 'menuitemradio',\n 'radio',\n 'switch'\n ],\n // 5.3 input type=\"image\"\n namingMethods: [\n 'altText',\n 'valueText',\n 'labelText',\n 'titleText',\n 'buttonDefaultText'\n ]\n },\n radio: {\n matches: {\n properties: {\n type: 'radio'\n }\n },\n allowedRoles: ['menuitemradio'],\n implicitAttrs: {\n 'aria-checked': 'false'\n }\n },\n textWithList: {\n matches: {\n properties: {\n type: 'text'\n },\n attributes: {\n list: '/.*/'\n }\n },\n allowedRoles: false\n },\n default: {\n // Note: spec change (do not count as phrasing)\n contentTypes: ['interactive', 'flow'],\n allowedRoles: ['combobox', 'searchbox', 'spinbutton'],\n implicitAttrs: {\n 'aria-valuenow': ''\n },\n // 5.1 input type=\"text\", input type=\"password\", input type=\"search\", input type=\"tel\", input type=\"url\"\n // 5.7 Other Form Elements\n namingMethods: ['labelText', 'placeholderText']\n }\n }\n },\n ins: {\n contentTypes: ['phrasing', 'flow'],\n allowedRoles: true\n },\n kbd: {\n contentTypes: ['phrasing', 'flow'],\n allowedRoles: true\n },\n label: {\n contentTypes: ['interactive', 'phrasing', 'flow'],\n allowedRoles: false,\n chromiumRole: 'Label'\n },\n legend: {\n allowedRoles: false\n },\n li: {\n allowedRoles: [\n 'menuitem',\n 'menuitemcheckbox',\n 'menuitemradio',\n 'option',\n 'none',\n 'presentation',\n 'radio',\n 'separator',\n 'tab',\n 'treeitem',\n 'doc-biblioentry',\n 'doc-endnote'\n ],\n implicitAttrs: {\n 'aria-setsize': '1',\n 'aria-posinset': '1'\n }\n },\n link: {\n contentTypes: ['phrasing', 'flow'],\n allowedRoles: false,\n noAriaAttrs: true\n },\n main: {\n contentTypes: ['flow'],\n allowedRoles: false,\n shadowRoot: true\n },\n map: {\n contentTypes: ['phrasing', 'flow'],\n allowedRoles: false,\n noAriaAttrs: true\n },\n math: {\n contentTypes: ['embedded', 'phrasing', 'flow'],\n allowedRoles: false\n },\n mark: {\n contentTypes: ['phrasing', 'flow'],\n allowedRoles: true\n },\n menu: {\n contentTypes: ['flow'],\n allowedRoles: [\n 'directory',\n 'group',\n 'listbox',\n 'menu',\n 'menubar',\n 'none',\n 'presentation',\n 'radiogroup',\n 'tablist',\n 'toolbar',\n 'tree'\n ]\n },\n meta: {\n variant: {\n itemprop: {\n matches: '[itemprop]',\n contentTypes: ['phrasing', 'flow']\n }\n },\n allowedRoles: false,\n noAriaAttrs: true\n },\n meter: {\n contentTypes: ['phrasing', 'flow'],\n allowedRoles: false,\n chromiumRole: 'progressbar'\n },\n nav: {\n contentTypes: ['sectioning', 'flow'],\n allowedRoles: [\n 'doc-index',\n 'doc-pagelist',\n 'doc-toc',\n 'menu',\n 'menubar',\n 'none',\n 'presentation',\n 'tablist'\n ],\n shadowRoot: true\n },\n noscript: {\n contentTypes: ['phrasing', 'flow'],\n allowedRoles: false,\n noAriaAttrs: true\n },\n object: {\n variant: {\n usemap: {\n matches: '[usemap]',\n contentTypes: ['interactive', 'embedded', 'phrasing', 'flow']\n },\n default: {\n contentTypes: ['embedded', 'phrasing', 'flow']\n }\n },\n allowedRoles: ['application', 'document', 'img'],\n chromiumRole: 'PluginObject'\n },\n ol: {\n contentTypes: ['flow'],\n allowedRoles: [\n 'directory',\n 'group',\n 'listbox',\n 'menu',\n 'menubar',\n 'none',\n 'presentation',\n 'radiogroup',\n 'tablist',\n 'toolbar',\n 'tree'\n ]\n },\n optgroup: {\n allowedRoles: false\n },\n option: {\n allowedRoles: false,\n implicitAttrs: {\n 'aria-selected': 'false'\n }\n },\n output: {\n contentTypes: ['phrasing', 'flow'],\n allowedRoles: true,\n // 5.6 output Element\n namingMethods: ['subtreeText']\n },\n p: {\n contentTypes: ['flow'],\n allowedRoles: true,\n shadowRoot: true\n },\n param: {\n allowedRoles: false,\n noAriaAttrs: true\n },\n picture: {\n // Note: spec change (do not count as embedded), because browsers do not hide text inside the picture element\n contentTypes: ['phrasing', 'flow'],\n allowedRoles: false,\n noAriaAttrs: true\n },\n pre: {\n contentTypes: ['flow'],\n allowedRoles: true\n },\n progress: {\n contentTypes: ['phrasing', 'flow'],\n allowedRoles: false,\n implicitAttrs: {\n 'aria-valuemax': '100',\n 'aria-valuemin': '0',\n 'aria-valuenow': '0'\n }\n },\n q: {\n contentTypes: ['phrasing', 'flow'],\n allowedRoles: true\n },\n rp: {\n allowedRoles: true\n },\n rt: {\n allowedRoles: true\n },\n ruby: {\n contentTypes: ['phrasing', 'flow'],\n allowedRoles: true\n },\n s: {\n contentTypes: ['phrasing', 'flow'],\n allowedRoles: true\n },\n samp: {\n contentTypes: ['phrasing', 'flow'],\n allowedRoles: true\n },\n script: {\n contentTypes: ['phrasing', 'flow'],\n allowedRoles: false,\n noAriaAttrs: true\n },\n search: {\n contentTypes: ['flow'],\n allowedRoles: ['form', 'group', 'none', 'presentation', 'region', 'search']\n },\n section: {\n contentTypes: ['sectioning', 'flow'],\n allowedRoles: [\n 'alert',\n 'alertdialog',\n 'application',\n 'banner',\n 'complementary',\n 'contentinfo',\n 'dialog',\n 'document',\n 'feed',\n 'group',\n 'log',\n 'main',\n 'marquee',\n 'navigation',\n 'none',\n 'note',\n 'presentation',\n 'search',\n 'status',\n 'tabpanel',\n 'doc-abstract',\n 'doc-acknowledgments',\n 'doc-afterword',\n 'doc-appendix',\n 'doc-bibliography',\n 'doc-chapter',\n 'doc-colophon',\n 'doc-conclusion',\n 'doc-credit',\n 'doc-credits',\n 'doc-dedication',\n 'doc-endnotes',\n 'doc-epigraph',\n 'doc-epilogue',\n 'doc-errata',\n 'doc-example',\n 'doc-foreword',\n 'doc-glossary',\n 'doc-index',\n 'doc-introduction',\n 'doc-notice',\n 'doc-pagelist',\n 'doc-part',\n 'doc-preface',\n 'doc-prologue',\n 'doc-pullquote',\n 'doc-qna',\n 'doc-toc'\n ],\n shadowRoot: true\n },\n select: {\n variant: {\n combobox: {\n matches: {\n attributes: {\n multiple: null,\n size: [null, '1']\n }\n },\n allowedRoles: ['menu']\n },\n default: {\n allowedRoles: false\n }\n },\n contentTypes: ['interactive', 'phrasing', 'flow'],\n implicitAttrs: {\n 'aria-valuenow': ''\n },\n // 5.7 Other form elements\n namingMethods: ['labelText']\n },\n slot: {\n contentTypes: ['phrasing', 'flow'],\n allowedRoles: false,\n noAriaAttrs: true\n },\n small: {\n contentTypes: ['phrasing', 'flow'],\n allowedRoles: true\n },\n source: {\n allowedRoles: false,\n noAriaAttrs: true\n },\n span: {\n contentTypes: ['phrasing', 'flow'],\n allowedRoles: true,\n shadowRoot: true\n },\n strong: {\n contentTypes: ['phrasing', 'flow'],\n allowedRoles: true\n },\n style: {\n allowedRoles: false,\n noAriaAttrs: true\n },\n svg: {\n contentTypes: ['embedded', 'phrasing', 'flow'],\n allowedRoles: true,\n chromiumRole: 'SVGRoot',\n namingMethods: ['svgTitleText']\n },\n sub: {\n contentTypes: ['phrasing', 'flow'],\n allowedRoles: true\n },\n summary: {\n allowedRoles: false,\n // 5.8 summary Element\n namingMethods: ['subtreeText']\n },\n sup: {\n contentTypes: ['phrasing', 'flow'],\n allowedRoles: true\n },\n table: {\n contentTypes: ['flow'],\n allowedRoles: true,\n // 5.11 table Element\n namingMethods: ['tableCaptionText', 'tableSummaryText']\n },\n tbody: {\n allowedRoles: true\n },\n template: {\n contentTypes: ['phrasing', 'flow'],\n allowedRoles: false,\n noAriaAttrs: true\n },\n textarea: {\n contentTypes: ['interactive', 'phrasing', 'flow'],\n allowedRoles: false,\n implicitAttrs: {\n 'aria-valuenow': '',\n 'aria-multiline': 'true'\n },\n // 5.1 textarea\n namingMethods: ['labelText', 'placeholderText']\n },\n tfoot: {\n allowedRoles: true\n },\n thead: {\n allowedRoles: true\n },\n time: {\n contentTypes: ['phrasing', 'flow'],\n allowedRoles: true\n },\n title: {\n allowedRoles: false,\n noAriaAttrs: true\n },\n td: {\n allowedRoles: true\n },\n th: {\n allowedRoles: true\n },\n tr: {\n allowedRoles: true\n },\n track: {\n allowedRoles: false,\n noAriaAttrs: true\n },\n u: {\n contentTypes: ['phrasing', 'flow'],\n allowedRoles: true\n },\n ul: {\n contentTypes: ['flow'],\n allowedRoles: [\n 'directory',\n 'group',\n 'listbox',\n 'menu',\n 'menubar',\n 'none',\n 'presentation',\n 'radiogroup',\n 'tablist',\n 'toolbar',\n 'tree'\n ]\n },\n var: {\n contentTypes: ['phrasing', 'flow'],\n allowedRoles: true\n },\n video: {\n variant: {\n controls: {\n matches: '[controls]',\n contentTypes: ['interactive', 'embedded', 'phrasing', 'flow']\n },\n default: {\n contentTypes: ['embedded', 'phrasing', 'flow']\n }\n },\n allowedRoles: ['application'],\n chromiumRole: 'video'\n },\n wbr: {\n contentTypes: ['phrasing', 'flow'],\n allowedRoles: ['presentation', 'none'],\n allowedAriaAttrs: ['aria-hidden']\n }\n};\nexport { htmlElms };\n\n\n// axe merges dpub + graphics roles into the ariaRoles table.\nexport const ariaRoles: Record<string, any> = { ...ariaRolesBase, ...dpubRoles, ...graphicsRoles };\n","/**\n * Core adaptation layer for the vendored axe-core accessibility checks.\n *\n * axe-core operates on its own `VirtualNode` abstraction. We scan static HTML\n * with jsdom and have real DOM nodes, so this module provides a thin `VNode`\n * wrapper over a real DOM `Node` that exposes the same surface axe's check/commons\n * code expects (`.props`, `.attr()`, `.hasAttr()`, `.attrNames`, `.children`,\n * `.parent`, `.actualNode`). Wrappers are cached per DOM node (WeakMap) so node\n * identity is stable — required by the accessible-name loop guard and by the\n * table header caches.\n *\n * Shadow DOM is intentionally ignored: scanned HTML is parsed with\n * `runScripts:'outside-only'` and contains no shadow roots.\n */\nimport { ariaAttrs } from './standards';\n\nexport type AnyNode = Node;\n\nexport interface VNodeProps {\n nodeType: number;\n nodeName: string;\n id: string;\n type?: string;\n nodeValue: string | null;\n multiple?: boolean;\n value?: string;\n selected?: boolean;\n checked?: boolean;\n indeterminate?: boolean;\n}\n\nconst VALID_INPUT_TYPES = [\n 'hidden', 'text', 'search', 'tel', 'url', 'email', 'password', 'date',\n 'month', 'week', 'time', 'datetime-local', 'number', 'range', 'color',\n 'checkbox', 'radio', 'file', 'submit', 'image', 'reset', 'button',\n];\n\nconst vnodeCache = new WeakMap<AnyNode, VNode>();\n\n/** Wrap a real DOM node, exposing the axe VirtualNode surface. */\nexport class VNode {\n actualNode: AnyNode;\n // axe sets these caches on the vNode; we keep them for parity behaviour.\n _isDisabled?: boolean;\n _inDisabledFieldset?: boolean;\n _rowHeaders?: unknown;\n _colHeaders?: unknown;\n // No shadow DOM in scanned HTML, but some code reads these.\n shadowId: undefined = undefined;\n elementInternals: undefined = undefined;\n\n private _props?: VNodeProps;\n\n constructor(node: AnyNode) {\n this.actualNode = node;\n }\n\n get props(): VNodeProps {\n if (this._props) return this._props;\n const node = this.actualNode as unknown as {\n nodeType: number;\n nodeName: string;\n id?: string;\n nodeValue: string | null;\n getAttribute?: (n: string) => string | null;\n multiple?: boolean;\n value?: string;\n selected?: boolean;\n checked?: boolean;\n indeterminate?: boolean;\n };\n const nodeName = node.nodeName.toLowerCase();\n let type: string | undefined;\n if (nodeName === 'input') {\n let t = (node.getAttribute?.('type') || '').toLowerCase();\n if (!VALID_INPUT_TYPES.includes(t)) t = 'text';\n type = t;\n }\n const props: VNodeProps = {\n nodeType: node.nodeType,\n nodeName,\n id: node.id ?? '',\n type,\n nodeValue: node.nodeValue,\n };\n if (node.nodeType === 1) {\n props.multiple = node.multiple;\n props.value = node.value;\n props.selected = node.selected;\n props.checked = node.checked;\n props.indeterminate = node.indeterminate;\n }\n this._props = props;\n return props;\n }\n\n attr(attrName: string): string | null {\n const n = this.actualNode as unknown as { getAttribute?: (n: string) => string | null };\n if (typeof n.getAttribute !== 'function') return null;\n return n.getAttribute(attrName);\n }\n\n hasAttr(attrName: string): boolean {\n const n = this.actualNode as unknown as { hasAttribute?: (n: string) => boolean };\n if (typeof n.hasAttribute !== 'function') return false;\n return n.hasAttribute(attrName);\n }\n\n get attrNames(): string[] {\n const n = this.actualNode as unknown as { getAttributeNames?: () => string[] };\n if (typeof n.getAttributeNames !== 'function') return [];\n return n.getAttributeNames();\n }\n\n get children(): VNode[] {\n return Array.from((this.actualNode as unknown as { childNodes: ArrayLike<AnyNode> }).childNodes).map(\n (c) => toVNode(c),\n );\n }\n\n get parent(): VNode | null {\n const p = (this.actualNode as unknown as { parentNode: AnyNode | null }).parentNode;\n if (!p || p.nodeType === 9 || p.nodeType === 11) return null;\n return toVNode(p);\n }\n\n getComputedStylePropertyValue(property: string): string {\n const el = this.actualNode as unknown as { ownerDocument?: { defaultView?: Window } };\n const view = el.ownerDocument?.defaultView;\n if (!view) return '';\n return view.getComputedStyle(this.actualNode as unknown as Element).getPropertyValue(property);\n }\n}\n\n/** Return the cached VNode for a DOM node (or pass through an existing VNode). */\nexport function toVNode(node: AnyNode | VNode): VNode {\n if (node instanceof VNode) return node;\n let v = vnodeCache.get(node);\n if (!v) {\n v = new VNode(node);\n vnodeCache.set(node, v);\n }\n return v;\n}\n\n/** axe's getNodeFromTree — here just returns the wrapping VNode. */\nexport function getNodeFromTree(node: AnyNode | VNode): VNode {\n return toVNode(node);\n}\n\n/** axe's nodeLookup — accepts a DOM node or VNode, returns both. */\nexport function nodeLookup(node: AnyNode | VNode): { vNode: VNode; domNode: AnyNode } {\n const vNode = toVNode(node);\n return { vNode, domNode: vNode.actualNode };\n}\n\nexport function isVNode(x: unknown): x is VNode {\n return x instanceof VNode;\n}\n\n// ── core/utils ───────────────────────────────────────────────────\n\nexport function tokenList(str: string | null | undefined): string[] {\n return (str || '')\n .trim()\n .replace(/\\s{2,}/g, ' ')\n .split(' ');\n}\n\nexport function parseTabindex(value: unknown): number | null {\n if (typeof value !== 'string') return null;\n const match = value.trim().match(/^([-+]?\\d+)/);\n if (match) return Number(match[1]);\n return null;\n}\n\nexport function uniqueArray<T>(arr1: T[], arr2: T[]): T[] {\n return arr1.concat(arr2).filter((elem, pos, arr) => arr.indexOf(elem) === pos);\n}\n\n/* eslint-disable */\n// oxlint-disable\n/** CSS.escape-style identifier escaping (from axe-core / mathiasbynens). */\nexport function escapeSelector(value: string): string {\n const string = String(value);\n const length = string.length;\n let index = -1;\n let codeUnit: number;\n let result = '';\n const firstCodeUnit = string.charCodeAt(0);\n while (++index < length) {\n codeUnit = string.charCodeAt(index);\n if (codeUnit == 0x0000) {\n result += '�';\n continue;\n }\n if (\n (codeUnit >= 0x0001 && codeUnit <= 0x001f) ||\n codeUnit == 0x007f ||\n (index == 0 && codeUnit >= 0x0030 && codeUnit <= 0x0039) ||\n (index == 1 && codeUnit >= 0x0030 && codeUnit <= 0x0039 && firstCodeUnit == 0x002d)\n ) {\n result += '\\\\' + codeUnit.toString(16) + ' ';\n continue;\n }\n if (index == 0 && length == 1 && codeUnit == 0x002d) {\n result += '\\\\' + string.charAt(index);\n continue;\n }\n if (\n codeUnit >= 0x0080 ||\n codeUnit == 0x002d ||\n codeUnit == 0x005f ||\n (codeUnit >= 0x0030 && codeUnit <= 0x0039) ||\n (codeUnit >= 0x0041 && codeUnit <= 0x005a) ||\n (codeUnit >= 0x0061 && codeUnit <= 0x007a)\n ) {\n result += string.charAt(index);\n continue;\n }\n result += '\\\\' + string.charAt(index);\n }\n return result;\n}\n/* eslint-enable */\n\n/**\n * memoize: axe memoizes for performance. Correctness never depends on it (the\n * accessible-name loop guard and table caches are handled explicitly), so this\n * is a passthrough.\n */\nexport function memoize<T extends (...args: never[]) => unknown>(fn: T): T {\n return fn;\n}\n\n/** axe's getRootNode adapted to real DOM. */\nexport function getRootNode(node: AnyNode): Document | DocumentFragment {\n const n = node as unknown as { getRootNode?: () => Node; ownerDocument?: Document };\n let doc = (n.getRootNode && n.getRootNode()) || (n.ownerDocument as unknown as Node);\n if (doc === node) doc = (n.ownerDocument as unknown as Node) ?? doc;\n return doc as Document | DocumentFragment;\n}\n\n/** Node#contains wrapper operating on VNodes. */\nexport function contains(vNode: VNode, otherVNode: VNode): boolean {\n const a = vNode.actualNode as unknown as { contains?: (n: AnyNode) => boolean };\n if (typeof a.contains === 'function') {\n return a.contains(otherVNode.actualNode);\n }\n let n: VNode | null = otherVNode;\n while (n) {\n if (n === vNode) return true;\n n = n.parent;\n }\n return false;\n}\n\n/** Array#sort callback to sort nodes (or VNodes) in DOM order. */\nexport function nodeSorter(a: AnyNode | VNode, b: AnyNode | VNode): number {\n const nodeA = (a instanceof VNode ? a.actualNode : a) as unknown as {\n compareDocumentPosition: (n: AnyNode) => number;\n };\n const nodeB = (b instanceof VNode ? b.actualNode : b) as unknown as AnyNode;\n if ((nodeA as unknown as AnyNode) === nodeB) return 0;\n return nodeA.compareDocumentPosition(nodeB) & 4 ? -1 : 1;\n}\n\n// ── commons/matches ──────────────────────────────────────────────\n\ntype Matcher = unknown;\n\nfunction fromPrimative(someString: unknown, matcher: Matcher): boolean {\n if (Array.isArray(matcher) && typeof someString !== 'undefined') {\n return matcher.includes(someString);\n }\n if (typeof matcher === 'function') {\n return !!(matcher as (s: unknown) => unknown)(someString);\n }\n if (someString !== null && someString !== undefined) {\n if (matcher instanceof RegExp) return matcher.test(String(someString));\n if (typeof matcher === 'string' && /^\\/.*\\/$/.test(matcher)) {\n const pattern = matcher.substring(1, matcher.length - 1);\n return new RegExp(pattern).test(String(someString));\n }\n }\n return matcher === someString;\n}\n\nfunction fromFunction(\n getValue: (prop: string) => unknown,\n matcher: Record<string, Matcher>,\n): boolean {\n if (typeof matcher !== 'object' || Array.isArray(matcher) || matcher instanceof RegExp) {\n throw new Error('Expect matcher to be an object');\n }\n return Object.keys(matcher).every((propName) => fromPrimative(getValue(propName), matcher[propName]));\n}\n\n// Role-based matchers are injected lazily to avoid import cycles with aria/text.\nlet getExplicitRoleFn: ((v: VNode) => string | null) | null = null;\nlet getImplicitRoleFn: ((v: VNode) => string | null) | null = null;\nlet getRoleFn: ((v: VNode) => string | null) | null = null;\nlet accessibleTextVirtualFn: ((v: VNode) => string) | null = null;\nexport function registerMatchers(fns: {\n getExplicitRole: (v: VNode) => string | null;\n getImplicitRole: (v: VNode) => string | null;\n getRole: (v: VNode) => string | null;\n accessibleTextVirtual: (v: VNode) => string;\n}): void {\n getExplicitRoleFn = fns.getExplicitRole;\n getImplicitRoleFn = fns.getImplicitRole;\n getRoleFn = fns.getRole;\n accessibleTextVirtualFn = fns.accessibleTextVirtual;\n}\n\nfunction fromDefinition(vNode: VNode, definition: Matcher): boolean {\n vNode = nodeLookup(vNode).vNode;\n if (Array.isArray(definition)) {\n return definition.some((d) => fromDefinition(vNode, d));\n }\n if (typeof definition === 'string') {\n return matchesSelector(vNode, definition);\n }\n const def = definition as Record<string, Matcher>;\n return Object.keys(def).every((matcherName) => {\n const matcher = def[matcherName];\n switch (matcherName) {\n case 'nodeName':\n return fromPrimative(vNode.props.nodeName, matcher);\n case 'attributes':\n return fromFunction((a) => vNode.attr(a), matcher as Record<string, Matcher>);\n case 'properties':\n return fromFunction(\n (p) => (vNode.props as unknown as Record<string, unknown>)[p],\n matcher as Record<string, Matcher>,\n );\n case 'condition':\n return !!(matcher as (n: VNode) => unknown)(vNode);\n case 'explicitRole':\n return fromPrimative(getExplicitRoleFn?.(vNode) ?? null, matcher);\n case 'implicitRole':\n return fromPrimative(getImplicitRoleFn?.(vNode) ?? null, matcher);\n case 'semanticRole':\n return fromPrimative(getRoleFn?.(vNode) ?? null, matcher);\n case 'hasAccessibleName':\n return fromPrimative(!!accessibleTextVirtualFn?.(vNode), matcher);\n default:\n throw new Error(`Unknown matcher type \"${matcherName}\"`);\n }\n });\n}\n\n/** Match a VNode against a CSS selector string using the real DOM. */\nfunction matchesSelector(vNode: VNode, selector: string): boolean {\n const el = vNode.actualNode as unknown as { matches?: (s: string) => boolean };\n if (typeof el.matches !== 'function') return false;\n try {\n return el.matches(selector);\n } catch {\n return false;\n }\n}\n\n/** axe.commons.matches: match a VNode against a definition (string/array/object). */\nexport function matches(vNode: VNode, definition: Matcher): boolean {\n return fromDefinition(vNode, definition);\n}\n\n/** axe.utils.closest over VNodes. */\nexport function closest(vNode: VNode | null, selector: string): VNode | null {\n while (vNode) {\n if (matches(vNode, selector)) return vNode;\n if (typeof vNode.parent === 'undefined') {\n throw new TypeError('Cannot resolve parent for non-DOM nodes');\n }\n vNode = vNode.parent;\n }\n return null;\n}\n\n/** axe.commons.dom.findUp adapted: walk up the real DOM via Element#closest. */\nexport function findUp(node: AnyNode | VNode, target: string): Element | null {\n const dom = (node instanceof VNode ? node.actualNode : node) as unknown as {\n closest?: (s: string) => Element | null;\n };\n if (typeof dom.closest !== 'function') return null;\n return dom.closest(target);\n}\n\n/** isHtmlElement: valid (non-SVG) HTML element per the standards table. */\nexport function isHtmlElement(node: VNode | Element): boolean {\n // Lazy import to avoid cycle with standards is unnecessary (standards is pure data).\n const v = node instanceof VNode ? node : toVNode(node as unknown as AnyNode);\n const nodeName = v.props.nodeName;\n const ns = (v.actualNode as unknown as { namespaceURI?: string }).namespaceURI;\n if (ns === 'http://www.w3.org/2000/svg') return false;\n return !!htmlElmsRef[nodeName];\n}\n\n// Imported here (not at top) to keep isHtmlElement's standards access explicit.\nimport { htmlElms as htmlElmsRef } from './standards';\n\n/** Expose ariaAttrs for callers needing attribute metadata via core. */\nexport { ariaAttrs };\n","/**\n * Vendored axe-core `commons/dom` helpers, adapted to real jsdom DOM.\n *\n * jsdom has no layout engine (no element geometry), so the geometry-dependent\n * visibility heuristics axe uses (overflow/scroll/clip-by-rect/offscreen) cannot\n * run. We keep the layout-independent visibility model — `display:none`,\n * `visibility:hidden|collapse`, `opacity:0`, the `hidden` attribute,\n * `aria-hidden`, `inert`, natively-hidden tags, and closed `<details>` — which\n * is exactly what `window.getComputedStyle` reports identically for both this\n * port and the original axe-in-jsdom oracle. Geometry-only hiding is treated as\n * \"not hidden\" (documented divergence; never affects ARIA/table/parsing rules).\n */\nimport {\n VNode,\n nodeLookup,\n getNodeFromTree,\n tokenList,\n getRootNode as utilGetRootNode,\n parseTabindex,\n type AnyNode,\n} from './core';\nimport { getAriaValue, getExplicitRole } from './aria';\n\nexport function getRootNode(node: AnyNode): Document | DocumentFragment {\n return utilGetRootNode(node);\n}\n\nexport function getComposedParent(element: AnyNode): AnyNode | null {\n const el = element as unknown as { parentNode: AnyNode | null };\n if (el.parentNode && el.parentNode.nodeType === 1) return el.parentNode;\n return null;\n}\n\n// ── idref resolution ─────────────────────────────────────────────\n\nexport function idrefs(node: VNode | AnyNode, attr: string): (AnyNode | null)[] {\n const dom = (node instanceof VNode ? node.actualNode : node) as unknown as {\n getAttribute: (a: string) => string | null;\n };\n try {\n const doc = getRootNode(node instanceof VNode ? node.actualNode : node) as unknown as {\n getElementById: (id: string) => AnyNode | null;\n };\n const result: (AnyNode | null)[] = [];\n let attrValue = dom.getAttribute(attr);\n if (attrValue) {\n const tokens = tokenList(attrValue);\n for (let i = 0; i < tokens.length; i++) result.push(doc.getElementById(tokens[i]));\n }\n return result;\n } catch {\n throw new TypeError('Cannot resolve id references for non-DOM nodes');\n }\n}\n\nexport function getResolvedRefs(\n node: VNode | AnyNode,\n attr: string,\n options: { self?: boolean } = {},\n): (VNode | null)[] {\n const { self = true } = options;\n const { vNode, domNode } = nodeLookup(node);\n try {\n const attrValue = vNode.attr(attr);\n if (!attrValue) return [];\n const doc = getRootNode(domNode) as unknown as { getElementById: (id: string) => AnyNode | null };\n let refs = tokenList(attrValue).map((value) => doc.getElementById(value));\n if (!self) refs = refs.filter((n) => n !== domNode);\n return refs.map((n) => (n ? getNodeFromTree(n) : null));\n } catch {\n throw new TypeError('Cannot resolve id references for non-DOM nodes');\n }\n}\n\n// ── visibility primitives ────────────────────────────────────────\n\nfunction nativelyHidden(vNode: VNode): boolean {\n return ['style', 'script', 'noscript', 'template'].includes(vNode.props.nodeName);\n}\n\nfunction displayHidden(vNode: VNode): boolean {\n if (vNode.props.nodeName === 'area') return false;\n return vNode.getComputedStylePropertyValue('display') === 'none';\n}\n\nfunction visibilityHidden(vNode: VNode, { isAncestor }: { isAncestor?: boolean } = {}): boolean {\n return !isAncestor && ['hidden', 'collapse'].includes(vNode.getComputedStylePropertyValue('visibility'));\n}\n\nfunction contentVisibilityHidden(vNode: VNode, { isAncestor }: { isAncestor?: boolean } = {}): boolean {\n return !!isAncestor && vNode.getComputedStylePropertyValue('content-visibility') === 'hidden';\n}\n\nfunction detailsHidden(vNode: VNode): boolean {\n if (vNode.parent?.props.nodeName !== 'details') return false;\n if (vNode.props.nodeName === 'summary') {\n const firstSummary = vNode.parent.children.find((node) => node.props.nodeName === 'summary');\n if (firstSummary === vNode) return false;\n }\n return !vNode.parent.hasAttr('open');\n}\n\nexport function ariaHidden(vNode: VNode): boolean {\n return getAriaValue(vNode, 'aria-hidden', { lowercase: true })?.value === 'true';\n}\n\nfunction opacityHidden(vNode: VNode): boolean {\n return vNode.getComputedStylePropertyValue('opacity') === '0';\n}\n\nconst clipRegex = /rect\\s*\\(([0-9]+)px,?\\s*([0-9]+)px,?\\s*([0-9]+)px,?\\s*([0-9]+)px\\s*\\)/;\nconst clipPathRegex = /(\\w+)\\((\\d+)/;\nfunction clipHidden(vNode: VNode): boolean {\n const matchesClip = vNode.getComputedStylePropertyValue('clip').match(clipRegex);\n const matchesClipPath = vNode.getComputedStylePropertyValue('clip-path').match(clipPathRegex);\n if (matchesClip && matchesClip.length === 5) {\n const position = vNode.getComputedStylePropertyValue('position');\n if (['fixed', 'absolute'].includes(position)) {\n return (\n Number(matchesClip[3]) - Number(matchesClip[1]) <= 0 &&\n Number(matchesClip[2]) - Number(matchesClip[4]) <= 0\n );\n }\n }\n if (matchesClipPath) {\n const type = matchesClipPath[1];\n const value = parseInt(matchesClipPath[2], 10);\n if (type === 'inset') return value >= 50;\n if (type === 'circle') return value === 0;\n }\n return false;\n}\n\nconst hiddenMethods = [displayHidden, visibilityHidden, contentVisibilityHidden, detailsHidden];\n\nfunction isHiddenSelf(vNode: VNode, isAncestor: boolean): boolean {\n if (nativelyHidden(vNode)) return true;\n if (!vNode.actualNode) return false;\n if (hiddenMethods.some((method) => method(vNode, { isAncestor }))) return true;\n if (!(vNode.actualNode as unknown as { isConnected?: boolean }).isConnected) return true;\n return false;\n}\n\nexport function isHiddenForEveryone(\n vNode: VNode | AnyNode,\n { skipAncestors, isAncestor = false }: { skipAncestors?: boolean; isAncestor?: boolean } = {},\n): boolean {\n vNode = nodeLookup(vNode).vNode;\n if (skipAncestors) return isHiddenSelf(vNode, isAncestor);\n let v: VNode | null = vNode;\n let ancestor = isAncestor;\n while (v) {\n if (isHiddenSelf(v, ancestor)) return true;\n v = v.parent;\n ancestor = true;\n }\n return false;\n}\n\nconst screenHiddenMethods = [opacityHidden, clipHidden];\n\nexport function isVisibleOnScreen(node: VNode | AnyNode): boolean {\n const vNode = nodeLookup(node).vNode;\n let v: VNode | null = vNode;\n let isAncestor = false;\n while (v) {\n if (isHiddenForEveryone(v, { skipAncestors: true, isAncestor })) return false;\n if (v.actualNode && screenHiddenMethods.some((method) => method(v as VNode))) return false;\n v = v.parent;\n isAncestor = true;\n }\n return true;\n}\n\n// ── inert ────────────────────────────────────────────────────────\n\nexport function isInert(\n vNode: VNode,\n { skipAncestors }: { skipAncestors?: boolean; isAncestor?: boolean } = {},\n): boolean {\n if (skipAncestors) return vNode.hasAttr('inert');\n let v: VNode | null = vNode;\n while (v) {\n if (v.hasAttr('inert')) return true;\n v = v.parent;\n }\n return false;\n}\n\nexport function isVisibleToScreenReaders(node: VNode | AnyNode): boolean {\n const vNode = nodeLookup(node).vNode;\n let v: VNode | null = vNode;\n let isAncestor = false;\n while (v) {\n if (ariaHidden(v) || isInert(v, { skipAncestors: true, isAncestor })) return false;\n if (isHiddenForEveryone(v, { skipAncestors: true, isAncestor })) return false;\n v = v.parent;\n isAncestor = true;\n }\n return true;\n}\n\n// ── focusability ─────────────────────────────────────────────────\n\nconst allowedDisabledNodeNames = [\n 'button', 'command', 'fieldset', 'keygen', 'optgroup', 'option', 'select', 'textarea', 'input',\n];\n\nexport function focusDisabled(el: VNode | AnyNode): boolean {\n const { vNode } = nodeLookup(el);\n if ((allowedDisabledNodeNames.includes(vNode.props.nodeName) && vNode.hasAttr('disabled')) || isInert(vNode)) {\n return true;\n }\n let parentNode = vNode.parent;\n let fieldsetDisabled = false;\n while (parentNode && !fieldsetDisabled) {\n if (parentNode.props.nodeName === 'legend') break;\n if (parentNode.props.nodeName === 'fieldset' && parentNode.hasAttr('disabled')) {\n fieldsetDisabled = true;\n }\n parentNode = parentNode.parent;\n }\n if (fieldsetDisabled) return true;\n if (vNode.props.nodeName !== 'area') {\n if (!vNode.actualNode) return false;\n return isHiddenForEveryone(vNode);\n }\n return false;\n}\n\nexport function isNativelyFocusable(el: VNode | AnyNode): boolean {\n const { vNode } = nodeLookup(el);\n if (!vNode || focusDisabled(vNode)) return false;\n switch (vNode.props.nodeName) {\n case 'a':\n case 'area':\n if (vNode.hasAttr('href')) return true;\n break;\n case 'input':\n return vNode.props.type !== 'hidden';\n case 'textarea':\n case 'select':\n case 'summary':\n case 'button':\n return true;\n case 'details':\n return !(vNode.actualNode as unknown as Element).querySelectorAll('summary').length;\n }\n return false;\n}\n\nexport function isFocusable(el: VNode | AnyNode): boolean {\n const { vNode } = nodeLookup(el);\n if (vNode.props.nodeType !== 1) return false;\n if (focusDisabled(vNode)) return false;\n if (isNativelyFocusable(vNode)) return true;\n const tabindex = parseTabindex(vNode.attr('tabindex'));\n return tabindex !== null;\n}\n\nexport function isInTabOrder(el: VNode | AnyNode): boolean {\n const { vNode } = nodeLookup(el);\n if (vNode.props.nodeType !== 1) return false;\n const tabindex = parseTabindex(vNode.attr('tabindex'));\n if (tabindex !== null && tabindex <= -1) return false;\n return isFocusable(vNode);\n}\n\n/** querySelectorAll over a VNode's real DOM subtree, returning VNodes. */\nexport function querySelectorAll(vNode: VNode, selector: string): VNode[] {\n const el = vNode.actualNode as unknown as { querySelectorAll?: (s: string) => ArrayLike<AnyNode> };\n if (typeof el.querySelectorAll !== 'function') return [];\n return Array.from(el.querySelectorAll(selector)).map((n) => getNodeFromTree(n));\n}\n\n// ── content detection ────────────────────────────────────────────\n\nconst visualRoles = [\n 'checkbox', 'img', 'meter', 'progressbar', 'scrollbar', 'radio', 'slider', 'spinbutton', 'textbox',\n];\n\nexport function isVisualContent(el: VNode | AnyNode): boolean {\n const { vNode } = nodeLookup(el);\n const role = getExplicitRole(vNode);\n if (role) return visualRoles.indexOf(role) !== -1;\n switch (vNode.props.nodeName) {\n case 'img':\n case 'iframe':\n case 'object':\n case 'video':\n case 'audio':\n case 'canvas':\n case 'svg':\n case 'math':\n case 'button':\n case 'select':\n case 'textarea':\n case 'keygen':\n case 'progress':\n case 'meter':\n return true;\n case 'input':\n return vNode.props.type !== 'hidden';\n default:\n return false;\n }\n}\n\nconst hiddenTextElms = [\n 'head', 'title', 'template', 'script', 'style', 'iframe', 'object', 'video', 'audio', 'noscript',\n];\n\nexport function hasChildTextNodes(elm: VNode): boolean {\n if (hiddenTextElms.includes(elm.props.nodeName)) return false;\n return elm.children.some(({ props }) => props.nodeType === 3 && (props.nodeValue || '').trim());\n}\n\nexport function hasContentVirtual(elm: VNode, noRecursion?: boolean, ignoreAria?: boolean): boolean {\n return (\n hasChildTextNodes(elm) ||\n isVisualContent(elm.actualNode) ||\n (!ignoreAria && !!labelVirtualAria(elm)) ||\n (!noRecursion &&\n elm.children.some((child) => child.actualNode.nodeType === 1 && hasContentVirtual(child)))\n );\n}\n\nexport function hasContent(elm: AnyNode, noRecursion?: boolean, ignoreAria?: boolean): boolean {\n return hasContentVirtual(getNodeFromTree(elm), noRecursion, ignoreAria);\n}\n\nexport function isHTML5(doc: Document): boolean {\n const node = (doc as unknown as { doctype: { name: string; publicId: string; systemId: string } | null })\n .doctype;\n if (node === null) return false;\n return node.name === 'html' && !node.publicId && !node.systemId;\n}\n\n// Lazy import to break aria↔dom cycle (labelVirtual lives in aria).\nimport { labelVirtual as labelVirtualAria } from './aria';\n","/**\n * Vendored axe-core `commons/table` helpers, adapted to real jsdom DOM. These\n * operate directly on real table elements/cells (as axe's table checks do).\n *\n * `isDataTable` keeps axe's full heuristic. The geometry-based branches\n * (offsetWidth/clientWidth borders, viewport width) degrade to their jsdom\n * (zero-layout) values exactly as the original axe-in-jsdom oracle saw them, so\n * data/layout classification stays in parity for our fixtures.\n */\nimport { VNode, toVNode, escapeSelector, memoize, findUp, type AnyNode } from './core';\nimport { getExplicitRole, getRoleType } from './aria';\nimport { isFocusable } from './dom';\n\ntype Cell = AnyNode & {\n nodeName: string;\n getAttribute: (a: string) => string | null;\n colSpan: number;\n rowSpan: number;\n textContent: string;\n children: ArrayLike<unknown>;\n};\ntype Table = AnyNode & {\n rows: ArrayLike<{ cells: ArrayLike<Cell> }>;\n};\n\nexport function getAllCells(tableElm: Table): Cell[] {\n const cells: Cell[] = [];\n for (let r = 0; r < tableElm.rows.length; r++) {\n const row = tableElm.rows[r];\n for (let c = 0; c < row.cells.length; c++) cells.push(row.cells[c]);\n }\n return cells;\n}\n\nfunction toGridImpl(node: Table): Cell[][] {\n const table: Cell[][] = [];\n const rows = node.rows;\n for (let i = 0; i < rows.length; i++) {\n const cells = rows[i].cells;\n table[i] = table[i] || [];\n let columnIndex = 0;\n for (let j = 0; j < cells.length; j++) {\n for (let colSpan = 0; colSpan < cells[j].colSpan; colSpan++) {\n const rowspanAttr = cells[j].getAttribute('rowspan');\n const rowspanValue =\n parseInt(rowspanAttr as string, 10) === 0 || (cells[j] as unknown as { rowspan?: number }).rowspan === 0\n ? rows.length\n : cells[j].rowSpan;\n for (let rowSpan = 0; rowSpan < rowspanValue; rowSpan++) {\n table[i + rowSpan] = table[i + rowSpan] || [];\n while (table[i + rowSpan][columnIndex]) columnIndex++;\n table[i + rowSpan][columnIndex] = cells[j];\n }\n columnIndex++;\n }\n }\n }\n return table;\n}\n\nexport const toGrid = memoize(toGridImpl);\nexport const toArray = toGrid;\n\nfunction getCellPositionImpl(cell: Cell, tableGrid?: Cell[][]): { x: number; y: number } | undefined {\n if (!tableGrid) tableGrid = toGrid(findUp(cell, 'table') as unknown as Table);\n for (let rowIndex = 0; rowIndex < tableGrid.length; rowIndex++) {\n if (tableGrid[rowIndex]) {\n const index = tableGrid[rowIndex].indexOf(cell);\n if (index !== -1) return { x: index, y: rowIndex };\n }\n }\n return undefined;\n}\n\nexport const getCellPosition = memoize(getCellPositionImpl);\n\nexport function getScope(el: Cell | VNode): boolean | string {\n const vNode = toVNode(el instanceof VNode ? el.actualNode : el);\n const cell = vNode.actualNode as unknown as Cell;\n const scope = vNode.attr('scope');\n const role = getExplicitRole(vNode);\n\n if (!['td', 'th'].includes(vNode.props.nodeName)) {\n throw new TypeError('Expected TD or TH element');\n }\n if (role === 'columnheader') return 'col';\n if (role === 'rowheader') return 'row';\n if (scope === 'col' || scope === 'row') return scope;\n if (vNode.props.nodeName !== 'th') return false;\n if (!vNode.actualNode) return 'auto';\n\n const tableGrid = toGrid(findUp(cell, 'table') as unknown as Table);\n const pos = getCellPosition(cell, tableGrid)!;\n const headerRow = tableGrid[pos.y].every((node) => (node as Cell).nodeName.toUpperCase() === 'TH');\n if (headerRow) return 'col';\n const headerCol = tableGrid\n .map((col) => col[pos.x])\n .every((node) => node && (node as Cell).nodeName.toUpperCase() === 'TH');\n if (headerCol) return 'row';\n return 'auto';\n}\n\nexport function isColumnHeader(element: Cell | VNode): boolean {\n return ['col', 'auto'].indexOf(getScope(element) as string) !== -1;\n}\n\nexport function isRowHeader(cell: Cell | VNode): boolean {\n return ['row', 'auto'].includes(getScope(cell) as string);\n}\n\nexport function isDataCell(cell: Cell): boolean {\n if (!cell.children.length && !cell.textContent.trim()) return false;\n const role = getExplicitRole(cell);\n if (role) return ['cell', 'gridcell'].includes(role);\n return cell.nodeName.toUpperCase() === 'TD';\n}\n\nexport function isHeader(cell: Cell): boolean {\n if (isColumnHeader(cell) || isRowHeader(cell)) return true;\n const id = cell.getAttribute('id');\n if (id) {\n const doc = (cell as unknown as { ownerDocument: { querySelector: (s: string) => unknown } }).ownerDocument;\n return !!doc.querySelector(`[headers~=\"${escapeSelector(id)}\"]`);\n }\n return false;\n}\n\nfunction traverseForHeaders(headerType: 'row' | 'col', position: { x: number; y: number }, tableGrid: Cell[][]): Cell[] {\n const property = headerType === 'row' ? '_rowHeaders' : '_colHeaders';\n const predicate = headerType === 'row' ? isRowHeader : isColumnHeader;\n const startCell = tableGrid[position.y][position.x];\n\n const colspan = startCell.colSpan - 1;\n const rowspanAttr = startCell.getAttribute('rowspan');\n const rowspanValue =\n parseInt(rowspanAttr as string, 10) === 0 || (startCell as unknown as { rowspan?: number }).rowspan === 0\n ? tableGrid.length\n : startCell.rowSpan;\n const rowspan = rowspanValue - 1;\n\n const rowStart = position.y + rowspan;\n const colStart = position.x + colspan;\n const rowEnd = headerType === 'row' ? position.y : 0;\n const colEnd = headerType === 'row' ? 0 : position.x;\n\n let headers: Cell[] | undefined;\n const cells: Cell[] = [];\n for (let row = rowStart; row >= rowEnd && !headers; row--) {\n for (let col = colStart; col >= colEnd; col--) {\n const cell = tableGrid[row] ? tableGrid[row][col] : undefined;\n if (!cell) continue;\n const vNode = toVNode(cell) as unknown as Record<string, Cell[] | undefined>;\n if (vNode[property]) {\n headers = vNode[property];\n break;\n }\n cells.push(cell);\n }\n }\n headers = (headers || []).concat(cells.filter(predicate));\n cells.forEach((tableCell) => {\n (toVNode(tableCell) as unknown as Record<string, Cell[]>)[property] = headers as Cell[];\n });\n return headers;\n}\n\nexport function getHeaders(cell: Cell, tableGrid?: Cell[][]): (Cell | null)[] {\n if (cell.getAttribute('headers')) {\n const headers = idrefs(cell, 'headers') as (Cell | null)[];\n if (headers.filter((header) => header).length) return headers;\n }\n if (!tableGrid) tableGrid = toGrid(findUp(cell, 'table') as unknown as Table);\n const position = getCellPosition(cell, tableGrid)!;\n const rowHeaders = traverseForHeaders('row', position, tableGrid);\n const colHeaders = traverseForHeaders('col', position, tableGrid);\n return ([] as (Cell | null)[]).concat(rowHeaders, colHeaders).reverse();\n}\n\ntype Dir = { x: number; y: number };\nfunction traverseTable(\n dir: Dir,\n position: { x: number; y: number },\n tableGrid: Cell[][],\n callback?: (cell: Cell, pos: { x: number; y: number }, grid: Cell[][]) => boolean | void,\n): Cell[] {\n const cell = tableGrid[position.y] ? tableGrid[position.y][position.x] : undefined;\n if (!cell) return [];\n if (typeof callback === 'function') {\n if (callback(cell, position, tableGrid) === true) return [cell];\n }\n const result = traverseTable(dir, { x: position.x + dir.x, y: position.y + dir.y }, tableGrid, callback);\n result.unshift(cell);\n return result;\n}\n\nexport function traverse(\n dir: Dir | string,\n startPos: { x: number; y: number } | Cell[][],\n tableGrid?: Cell[][] | ((cell: Cell) => boolean | void),\n callback?: (cell: Cell) => boolean | void,\n): Cell[] {\n let pos: { x: number; y: number };\n let grid: Cell[][];\n let cb: ((cell: Cell, p: { x: number; y: number }, g: Cell[][]) => boolean | void) | undefined;\n if (Array.isArray(startPos)) {\n cb = tableGrid as (cell: Cell) => boolean | void;\n grid = startPos as Cell[][];\n pos = { x: 0, y: 0 };\n } else {\n pos = startPos as { x: number; y: number };\n grid = tableGrid as Cell[][];\n cb = callback as (cell: Cell) => boolean | void;\n }\n let d: Dir;\n if (typeof dir === 'string') {\n d = { left: { x: -1, y: 0 }, up: { x: 0, y: -1 }, right: { x: 1, y: 0 }, down: { x: 0, y: 1 } }[dir]!;\n } else {\n d = dir;\n }\n return traverseTable(d, { x: pos.x + d.x, y: pos.y + d.y }, grid, cb);\n}\n\n// ── isDataTable ──────────────────────────────────────────────────\n\nexport function isDataTable(node: Table): boolean {\n const role = getExplicitRole(node);\n if ((role === 'presentation' || role === 'none') && !isFocusable(node)) return false;\n\n const el = node as unknown as {\n getAttribute: (a: string) => string | null;\n tHead?: unknown;\n tFoot?: unknown;\n caption?: unknown;\n children: ArrayLike<{ nodeName: string }>;\n getElementsByTagName: (t: string) => ArrayLike<unknown>;\n querySelector: (s: string) => unknown;\n ownerDocument: { defaultView: Window | null };\n };\n\n if (el.getAttribute('contenteditable') === 'true' || findUp(node, '[contenteditable=\"true\"]')) return true;\n if (role === 'grid' || role === 'treegrid' || role === 'table') return true;\n if (getRoleType(role) === 'landmark') return true;\n if (el.getAttribute('datatable') === '0') return false;\n if (el.getAttribute('summary')) return true;\n if (el.tHead || el.tFoot || el.caption) return true;\n\n for (let ci = 0; ci < el.children.length; ci++) {\n if (el.children[ci].nodeName.toUpperCase() === 'COLGROUP') return true;\n }\n\n let cells = 0;\n const rows = node.rows;\n const rowLength = rows.length;\n let hasBorder = false;\n for (let ri = 0; ri < rowLength; ri++) {\n const row = rows[ri];\n for (let cellIndex = 0; cellIndex < row.cells.length; cellIndex++) {\n const cell = row.cells[cellIndex] as Cell & { offsetWidth?: number; clientWidth?: number; offsetHeight?: number; clientHeight?: number };\n if (cell.nodeName.toUpperCase() === 'TH') return true;\n if (\n !hasBorder &&\n (cell.offsetWidth !== cell.clientWidth || cell.offsetHeight !== cell.clientHeight)\n ) {\n hasBorder = true;\n }\n if (cell.getAttribute('scope') || cell.getAttribute('headers') || cell.getAttribute('abbr')) return true;\n if (['columnheader', 'rowheader'].includes(getExplicitRole(cell) as string)) return true;\n if (cell.children.length === 1 && (cell.children[0] as { nodeName: string }).nodeName.toUpperCase() === 'ABBR') {\n return true;\n }\n cells++;\n }\n }\n\n if (el.getElementsByTagName('table').length) return false;\n if (rowLength < 2) return false;\n\n const sampleRow = rows[Math.ceil(rowLength / 2)];\n if (sampleRow.cells.length === 1 && (sampleRow.cells[0] as Cell).colSpan === 1) return false;\n if (sampleRow.cells.length >= 5) return true;\n if (hasBorder) return true;\n\n const view = el.ownerDocument.defaultView;\n let bgColor: string | undefined;\n let bgImage: string | undefined;\n for (let ri = 0; ri < rowLength; ri++) {\n const row = rows[ri] as unknown as Element;\n const style = view ? view.getComputedStyle(row) : null;\n const rowBgColor = style ? style.getPropertyValue('background-color') : '';\n const rowBgImage = style ? style.getPropertyValue('background-image') : '';\n if (bgColor && bgColor !== rowBgColor) return true;\n bgColor = rowBgColor;\n if (bgImage && bgImage !== rowBgImage) return true;\n bgImage = rowBgImage;\n }\n\n if (rowLength >= 20) return true;\n\n const width = (node as unknown as { getBoundingClientRect?: () => { width: number } }).getBoundingClientRect?.().width ?? 0;\n const viewportWidth = (view as unknown as { innerWidth?: number })?.innerWidth || 1024;\n if (width > viewportWidth * 0.95) return false;\n if (cells < 10) return false;\n if (el.querySelector('object, embed, iframe, applet')) return false;\n return true;\n}\n\n// Lazy import to break aria/table cycle for idrefs.\nimport { idrefs } from './dom';\n","/**\n * Vendored axe-core `commons/text` (accessible-name computation) and the\n * autocomplete validator, adapted to real jsdom DOM via `VNode`.\n *\n * Icon-ligature detection (canvas-based) is dropped — our checks never request\n * it. Unicode/emoji helpers are not needed by the ported rules.\n */\nimport { VNode, getNodeFromTree, nodeLookup, type AnyNode } from './core';\nimport {\n getRole,\n getExplicitRole,\n getAriaValue,\n hasAriaValue,\n getOwnedVirtual,\n arialabelledbyText,\n arialabelText,\n namedFromContents,\n} from './aria';\nimport { isVisibleToScreenReaders, isVisibleOnScreen, isHiddenForEveryone } from './dom';\nimport { getElementSpec, getElementsByContentType } from './stdhelpers';\n\n// ── sanitize ─────────────────────────────────────────────────────\n\nexport function sanitize(str: string | null | undefined): string {\n if (!str) return '';\n return str\n .replace(/\\r\\n/g, '\\n')\n .replace(/\\u00A0/g, ' ')\n .replace(/[\\s]{2,}/g, ' ')\n .trim();\n}\n\n// ── forms predicates (commons/forms) ─────────────────────────────\n\nconst nonTextInputTypes = [\n 'button', 'checkbox', 'color', 'file', 'hidden', 'image', 'password', 'radio', 'reset', 'submit',\n];\n\nfunction isNativeTextbox(vNode: VNode): boolean {\n const nodeName = vNode.props.nodeName;\n return (\n nodeName === 'textarea' ||\n (nodeName === 'input' && !nonTextInputTypes.includes((vNode.attr('type') || '').toLowerCase()))\n );\n}\n\nfunction isNativeSelect(vNode: VNode): boolean {\n return vNode.props.nodeName === 'select';\n}\n\nfunction isAriaTextbox(vNode: VNode): boolean {\n return getExplicitRole(vNode) === 'textbox';\n}\n\nfunction isAriaListbox(vNode: VNode): boolean {\n return getExplicitRole(vNode) === 'listbox';\n}\n\nfunction isAriaCombobox(vNode: VNode): boolean {\n return getExplicitRole(vNode) === 'combobox';\n}\n\nconst rangeRoles = ['progressbar', 'scrollbar', 'slider', 'spinbutton'];\nfunction isAriaRange(vNode: VNode): boolean {\n return rangeRoles.includes(getExplicitRole(vNode) as string);\n}\n\nfunction qsa(vNode: VNode, selector: string): VNode[] {\n const el = vNode.actualNode as unknown as { querySelectorAll?: (s: string) => ArrayLike<AnyNode> };\n if (typeof el.querySelectorAll !== 'function') return [];\n return Array.from(el.querySelectorAll(selector)).map((n) => getNodeFromTree(n));\n}\n\n// ── visibleVirtual ───────────────────────────────────────────────\n\nexport function visibleVirtual(element: VNode | AnyNode, screenReader?: boolean, noRecursing?: boolean): string {\n const { vNode } = nodeLookup(element);\n const visibleMethod = screenReader ? isVisibleToScreenReaders : isVisibleOnScreen;\n const visible = !vNode.actualNode || visibleMethod(vNode);\n\n const result = vNode.children\n .map((child) => {\n const { nodeType, nodeValue, nodeName } = child.props;\n if (nodeType === 3) {\n if (!nodeValue || !visible) return '';\n return nodeValue;\n }\n if (nodeName === 'br') return ' ';\n if (!noRecursing) return visibleVirtual(child, screenReader, false);\n return '';\n })\n .join('');\n return sanitize(result);\n}\n\n// ── form control value ───────────────────────────────────────────\n\nconst unsupported = { accessibleNameFromFieldValue: ['progressbar'] };\n\nexport const controlValueRoles = [\n 'textbox', 'progressbar', 'scrollbar', 'slider', 'spinbutton', 'combobox', 'listbox',\n];\n\nfunction nativeTextboxValue(node: VNode): string {\n const { vNode } = nodeLookup(node);\n if (isNativeTextbox(vNode)) return vNode.props.value || '';\n return '';\n}\n\nfunction nativeSelectValue(node: VNode): string {\n const { vNode } = nodeLookup(node);\n if (!isNativeSelect(vNode)) return '';\n const options = qsa(vNode, 'option');\n const selectedOptions = options.filter((option) => option.props.selected);\n if (!selectedOptions.length && options.length) selectedOptions.push(options[0]);\n return selectedOptions.map((option) => visibleVirtual(option)).join(' ') || '';\n}\n\nfunction ariaTextboxValue(node: VNode): string {\n const { vNode, domNode } = nodeLookup(node);\n if (!isAriaTextbox(vNode)) return '';\n if (!domNode || !isHiddenForEveryone(domNode)) return visibleVirtual(vNode, true);\n return (domNode as unknown as { textContent: string }).textContent;\n}\n\nfunction ariaListboxValue(node: VNode, context: AccContext): string {\n const { vNode } = nodeLookup(node);\n if (!isAriaListbox(vNode)) return '';\n const selected = getOwnedVirtual(vNode).filter(\n (owned) => getRole(owned) === 'option' && getAriaValue(owned, 'aria-selected')?.value === 'true',\n );\n if (selected.length === 0) return '';\n return accessibleTextVirtual(selected[0], context);\n}\n\nfunction ariaComboboxValue(node: VNode, context: AccContext): string {\n const { vNode } = nodeLookup(node);\n if (!isAriaCombobox(vNode)) return '';\n const listbox = getOwnedVirtual(vNode).filter((elm) => getRole(elm) === 'listbox')[0];\n return listbox ? ariaListboxValue(listbox, context) : '';\n}\n\nfunction ariaRangeValue(node: VNode): string {\n const { vNode } = nodeLookup(node);\n if (!isAriaRange(vNode) || !hasAriaValue(vNode, 'aria-valuenow')) return '';\n const valueNow = +(getAriaValue(vNode, 'aria-valuenow')?.value as string);\n return !isNaN(valueNow) ? String(valueNow) : '0';\n}\n\nconst formControlValueMethods = [\n nativeTextboxValue,\n nativeSelectValue,\n ariaTextboxValue,\n ariaListboxValue,\n ariaComboboxValue,\n ariaRangeValue,\n];\n\nfunction formControlValue(virtualNode: VNode, context: AccContext = {}): string {\n const unsupportedRoles = unsupported.accessibleNameFromFieldValue || [];\n const role = getRole(virtualNode);\n if (\n context.startNode === virtualNode ||\n !controlValueRoles.includes(role as string) ||\n unsupportedRoles.includes(role as string)\n ) {\n return '';\n }\n return formControlValueMethods.reduce((accName: string, step) => accName || step(virtualNode, context), '');\n}\n\n// ── title / label / native text ──────────────────────────────────\n\nconst alwaysTitleElements = ['iframe'];\nfunction titleText(node: VNode): string {\n const { vNode } = nodeLookup(node);\n if (vNode.props.nodeType !== 1 || !vNode.hasAttr('title')) return '';\n if (!alwaysTitleElements.includes(vNode.props.nodeName) && ['none', 'presentation'].includes(getRole(vNode) as string)) {\n return '';\n }\n return vNode.attr('title') || '';\n}\n\nfunction attrText(attr: string, vNode: VNode): string {\n return vNode.attr(attr) || '';\n}\n\nfunction descendantText(nodeName: string, vNode: VNode, context: AccContext): string {\n nodeName = nodeName.toLowerCase();\n const actualNode = vNode.actualNode as unknown as {\n nodeName: string;\n querySelector: (s: string) => AnyNode | null;\n };\n const nodeNames = [nodeName, actualNode.nodeName.toLowerCase()].join(',');\n const candidate = actualNode.querySelector(nodeNames);\n if (!candidate || (candidate as unknown as { nodeName: string }).nodeName.toLowerCase() !== nodeName) {\n return '';\n }\n return accessibleText(candidate, context);\n}\n\nconst defaultButtonValues: Record<string, string> = {\n submit: 'Submit',\n image: 'Submit',\n reset: 'Reset',\n button: '',\n};\n\nconst nativeTextMethods: Record<string, (vNode: VNode, context: AccContext) => string> = {\n valueText: (vNode) => vNode.props.value || '',\n buttonDefaultText: (vNode) => defaultButtonValues[vNode.props.type as string] || '',\n tableCaptionText: (vNode, context) => descendantText('caption', vNode, context),\n figureText: (vNode, context) => descendantText('figcaption', vNode, context),\n svgTitleText: (vNode, context) => descendantText('title', vNode, context),\n fieldsetLegendText: (vNode, context) => descendantText('legend', vNode, context),\n altText: (vNode) => attrText('alt', vNode),\n tableSummaryText: (vNode) => attrText('summary', vNode),\n titleText: (vNode) => titleText(vNode),\n subtreeText: (vNode, context) => subtreeText(vNode, context),\n labelText: (vNode, context) => labelText(vNode, context),\n singleSpace: () => ' ',\n placeholderText: (vNode) => attrText('placeholder', vNode),\n};\n\nfunction nativeTextAlternative(virtualNode: VNode, context: AccContext = {}): string {\n if (virtualNode.props.nodeType !== 1 || ['presentation', 'none'].includes(getRole(virtualNode) as string)) {\n return '';\n }\n const elmSpec = getElementSpec(virtualNode, { noMatchAccessibleName: true }) as { namingMethods?: string[] };\n const methods = (elmSpec.namingMethods || []).map((name) => nativeTextMethods[name]);\n return methods.reduce((accName: string, step) => accName || (step ? step(virtualNode, context) : ''), '');\n}\n\n// ── label text (explicit + implicit <label>) ─────────────────────\n\nfunction findElmsInContext(elm: string, attr: string, value: string, context: AnyNode): AnyNode[] {\n const root = ((context as unknown as { nodeType: number }).nodeType === 9 ||\n (context as unknown as { nodeType: number }).nodeType === 11\n ? context\n : (context as unknown as { ownerDocument: AnyNode }).ownerDocument) as unknown as {\n querySelectorAll: (s: string) => ArrayLike<AnyNode>;\n };\n // value is an id; escape minimally via attribute selector quoting\n return Array.from(root.querySelectorAll(`${elm}[${attr}=\"${cssAttrEscape(value)}\"]`));\n}\n\nfunction cssAttrEscape(value: string): string {\n return value.replace(/[\"\\\\]/g, '\\\\$&');\n}\n\nfunction getExplicitLabels(virtualNode: VNode): AnyNode[] {\n if (!virtualNode.attr('id')) return [];\n if (!virtualNode.actualNode) {\n throw new TypeError('Cannot resolve explicit label reference for non-DOM nodes');\n }\n return findElmsInContext('label', 'for', virtualNode.attr('id') as string, virtualNode.actualNode);\n}\n\nfunction nodeSorterDom(a: AnyNode, b: AnyNode): number {\n if (a === b) return 0;\n return (a as unknown as { compareDocumentPosition: (n: AnyNode) => number }).compareDocumentPosition(b) & 4\n ? -1\n : 1;\n}\n\nfunction closestLabel(vNode: VNode): VNode | null {\n let v: VNode | null = vNode;\n while (v) {\n if (v.props.nodeName === 'label') return v;\n v = v.parent;\n }\n return null;\n}\n\nfunction labelText(virtualNode: VNode, context: AccContext = {}): string {\n if (\n context.inControlContext ||\n context.inLabelledByContext ||\n alreadyProcessed(virtualNode, context)\n ) {\n return '';\n }\n if (!context.startNode) context.startNode = virtualNode;\n\n const labelContext: AccContext = { inControlContext: true, ...context };\n const explicitLabels = getExplicitLabels(virtualNode);\n const implicitLabel = closestLabel(virtualNode);\n\n let labels: AnyNode[];\n if (implicitLabel) {\n labels = [...explicitLabels, implicitLabel.actualNode];\n labels.sort(nodeSorterDom);\n } else {\n labels = explicitLabels;\n }\n\n return labels\n .map((labelNode) => accessibleText(labelNode, labelContext))\n .filter((text) => text !== '')\n .join(' ');\n}\n\n// ── subtree text ─────────────────────────────────────────────────\n\nlet phrasingElementsCache: string[] | null = null;\nfunction phrasingElements(): string[] {\n if (!phrasingElementsCache) {\n phrasingElementsCache = getElementsByContentType('phrasing').concat(['#text']);\n }\n return phrasingElementsCache;\n}\n\nexport function subtreeText(virtualNode: VNode, context: AccContext = {}): string {\n context.startNode = context.startNode || virtualNode;\n const { strict, inControlContext, inLabelledByContext } = context;\n const role = getRole(virtualNode);\n const { contentTypes } = getElementSpec(virtualNode, { noMatchAccessibleName: true }) as {\n contentTypes?: string[];\n };\n if (\n alreadyProcessed(virtualNode, context) ||\n virtualNode.props.nodeType !== 1 ||\n contentTypes?.includes('embedded') ||\n controlValueRoles.includes(role as string)\n ) {\n return '';\n }\n if (!context.subtreeDescendant && !context.inLabelledByContext && !namedFromContents(virtualNode, { strict })) {\n return '';\n }\n if (!strict) {\n const subtreeDescendant = !inControlContext && !inLabelledByContext;\n context = { subtreeDescendant, ...context };\n }\n return getOwnedVirtual(virtualNode).reduce(\n (contentText: string, child) => appendAccessibleText(contentText, child, context),\n '',\n );\n}\n\nfunction appendAccessibleText(contentText: string, virtualNode: VNode, context: AccContext): string {\n const nodeName = virtualNode.props.nodeName;\n let contentTextAdd = accessibleTextVirtual(virtualNode, context);\n if (!contentTextAdd) return contentText;\n if (!phrasingElements().includes(nodeName)) {\n if (contentTextAdd[0] !== ' ') contentTextAdd += ' ';\n if (contentText && contentText[contentText.length - 1] !== ' ') contentTextAdd = ' ' + contentTextAdd;\n }\n return contentText + contentTextAdd;\n}\n\n// ── accessible text (top level) ──────────────────────────────────\n\nexport interface AccContext {\n startNode?: VNode;\n inControlContext?: boolean;\n inLabelledByContext?: boolean;\n includeHidden?: boolean;\n subtreeDescendant?: boolean;\n strict?: boolean;\n processed?: VNode[];\n}\n\nfunction alreadyProcessed(virtualNode: VNode, context: AccContext): boolean {\n context.processed = context.processed || [];\n if (context.processed.includes(virtualNode)) return true;\n context.processed.push(virtualNode);\n return false;\n}\n\nfunction nativelyHiddenTag(virtualNode: VNode): boolean {\n return ['style', 'script', 'noscript', 'template'].includes(virtualNode.props.nodeName);\n}\n\nfunction shouldIgnoreHidden(virtualNode: VNode, context: AccContext): boolean {\n if (!virtualNode) return false;\n if (context.includeHidden && !nativelyHiddenTag(virtualNode)) return false;\n if (virtualNode.props.nodeType !== 1) return false;\n return !isVisibleToScreenReaders(virtualNode);\n}\n\nfunction prepareContext(virtualNode: VNode, context: AccContext): AccContext {\n if (!context.startNode) context = { startNode: virtualNode, ...context };\n if (virtualNode.props.nodeType === 1 && context.inLabelledByContext && context.includeHidden === undefined) {\n context = { includeHidden: !isVisibleToScreenReaders(virtualNode), ...context };\n }\n return context;\n}\n\nexport function accessibleTextVirtual(virtualNode: VNode, context: AccContext = {}): string {\n context = prepareContext(virtualNode, context);\n if (shouldIgnoreHidden(virtualNode, context)) return '';\n\n const computationSteps = [\n arialabelledbyText,\n arialabelText,\n nativeTextAlternative,\n formControlValue,\n subtreeText,\n textNodeValue,\n titleText,\n ];\n\n return computationSteps.reduce((accName: string, step) => {\n if (context.startNode === virtualNode) accName = sanitize(accName);\n if (accName !== '') return accName;\n return (step as (v: VNode, c: AccContext) => string)(virtualNode, context);\n }, '');\n}\n\nfunction textNodeValue(virtualNode: VNode): string {\n if (virtualNode.props.nodeType !== 3) return '';\n return virtualNode.props.nodeValue || '';\n}\n\nexport function accessibleText(element: VNode | AnyNode, context?: AccContext): string {\n return accessibleTextVirtual(getNodeFromTree(element), context);\n}\n\n// ── autocomplete validity ────────────────────────────────────────\n\nconst autocomplete = {\n stateTerms: ['on', 'off'],\n standaloneTerms: [\n 'name', 'honorific-prefix', 'given-name', 'additional-name', 'family-name',\n 'honorific-suffix', 'nickname', 'username', 'new-password', 'current-password',\n 'organization-title', 'organization', 'street-address', 'address-line1',\n 'address-line2', 'address-line3', 'address-level4', 'address-level3',\n 'address-level2', 'address-level1', 'country', 'country-name', 'postal-code',\n 'cc-name', 'cc-given-name', 'cc-additional-name', 'cc-family-name', 'cc-number',\n 'cc-exp', 'cc-exp-month', 'cc-exp-year', 'cc-csc', 'cc-type',\n 'transaction-currency', 'transaction-amount', 'language', 'bday', 'bday-day',\n 'bday-month', 'bday-year', 'sex', 'url', 'photo', 'one-time-code',\n ],\n qualifiers: ['home', 'work', 'mobile', 'fax', 'pager'],\n qualifiedTerms: [\n 'tel', 'tel-country-code', 'tel-national', 'tel-area-code', 'tel-local',\n 'tel-local-prefix', 'tel-local-suffix', 'tel-extension', 'email', 'impp',\n ],\n locations: ['billing', 'shipping'],\n};\n\nexport function isValidAutocomplete(\n autocompleteValue: string,\n {\n looseTyped = false,\n stateTerms = [],\n locations = [],\n qualifiers = [],\n standaloneTerms = [],\n qualifiedTerms = [],\n ignoredValues = [],\n }: {\n looseTyped?: boolean;\n stateTerms?: string[];\n locations?: string[];\n qualifiers?: string[];\n standaloneTerms?: string[];\n qualifiedTerms?: string[];\n ignoredValues?: string[];\n } = {},\n): boolean | undefined {\n autocompleteValue = autocompleteValue.toLowerCase().trim();\n stateTerms = stateTerms.concat(autocomplete.stateTerms);\n if (stateTerms.includes(autocompleteValue) || autocompleteValue === '') return true;\n\n qualifiers = qualifiers.concat(autocomplete.qualifiers);\n locations = locations.concat(autocomplete.locations);\n standaloneTerms = standaloneTerms.concat(autocomplete.standaloneTerms);\n qualifiedTerms = qualifiedTerms.concat(autocomplete.qualifiedTerms);\n\n const autocompleteTerms = autocompleteValue.split(/\\s+/g);\n if (autocompleteTerms[autocompleteTerms.length - 1] === 'webauthn') {\n autocompleteTerms.pop();\n if (autocompleteTerms.length === 0) return false;\n }\n\n if (!looseTyped) {\n if (autocompleteTerms[0].length > 8 && autocompleteTerms[0].substr(0, 8) === 'section-') {\n autocompleteTerms.shift();\n }\n if (locations.includes(autocompleteTerms[0])) autocompleteTerms.shift();\n if (qualifiers.includes(autocompleteTerms[0])) {\n autocompleteTerms.shift();\n standaloneTerms = [];\n }\n if (autocompleteTerms.length !== 1) return false;\n }\n\n const purposeTerm = autocompleteTerms[autocompleteTerms.length - 1];\n if (ignoredValues.includes(purposeTerm)) return undefined;\n return standaloneTerms.includes(purposeTerm) || qualifiedTerms.includes(purposeTerm);\n}\n","/**\n * Standards-derived helpers (axe `commons/standards`): functions that read the\n * pure data tables in `standards.ts` — element specs, global ARIA attributes,\n * implicit HTML role mapping, content-type lookups.\n */\nimport { ariaAttrs, ariaRoles, htmlElms } from './standards';\nimport { VNode, matches, closest } from './core';\n\nexport function getAriaRolesByType(type: string): string[] {\n return Object.keys(ariaRoles).filter((roleName) => ariaRoles[roleName].type === type);\n}\n\nexport function getAriaRolesSupportingNameFromContent(): string[] {\n return Object.keys(ariaRoles).filter((roleName) => ariaRoles[roleName].nameFromContent);\n}\n\nexport function getGlobalAriaAttrs(): string[] {\n return Object.keys(ariaAttrs).filter((attrName) => ariaAttrs[attrName].global);\n}\n\nexport function getElementsByContentType(type: string): string[] {\n return Object.keys(htmlElms).filter((nodeName) => {\n const elm = htmlElms[nodeName];\n if (elm.contentTypes) return elm.contentTypes.includes(type);\n if (!elm.variant) return false;\n if (elm.variant.default && elm.variant.default.contentTypes) {\n return elm.variant.default.contentTypes.includes(type);\n }\n return false;\n });\n}\n\n/**\n * Return the spec for an HTML element, resolving variants against the node.\n */\nexport function getElementSpec(\n vNode: VNode,\n { noMatchAccessibleName = false }: { noMatchAccessibleName?: boolean } = {},\n): Record<string, unknown> {\n const standard = htmlElms[vNode.props.nodeName];\n if (!standard) return {};\n if (!standard.variant) return standard;\n\n const { variant, ...spec } = standard as { variant: Record<string, unknown> } & Record<string, unknown>;\n\n for (const variantName in variant) {\n if (!Object.prototype.hasOwnProperty.call(variant, variantName) || variantName === 'default') {\n continue;\n }\n const { matches: variantMatches, ...props } = variant[variantName] as Record<string, unknown>;\n const matchProperties = Array.isArray(variantMatches) ? variantMatches : [variantMatches];\n for (let i = 0; i < matchProperties.length && noMatchAccessibleName; i++) {\n if (Object.prototype.hasOwnProperty.call(matchProperties[i], 'hasAccessibleName')) {\n return standard;\n }\n }\n if (matches(vNode, variantMatches)) {\n for (const propName in props) {\n if (Object.prototype.hasOwnProperty.call(props, propName)) {\n (spec as Record<string, unknown>)[propName] = props[propName];\n }\n }\n }\n }\n\n const def = (variant as { default?: Record<string, unknown> }).default;\n for (const propName in def) {\n if (\n Object.prototype.hasOwnProperty.call(def, propName) &&\n typeof (spec as Record<string, unknown>)[propName] === 'undefined'\n ) {\n (spec as Record<string, unknown>)[propName] = def[propName];\n }\n }\n\n return spec;\n}\n\n// implicit-html-roles requires aria/dom/text helpers; imported lazily-safe\n// (called only at runtime, never at module init) to tolerate import cycles.\nimport { arialabelledbyText, arialabelText, getExplicitRole } from './aria';\nimport { idrefs, isFocusable } from './dom';\nimport { isColumnHeader, isRowHeader } from './table';\nimport { sanitize } from './text';\n\nconst getSectioningContentSelector = (): string =>\n getElementsByContentType('sectioning')\n .map((nodeName) => `${nodeName}:not([role])`)\n .join(', ') + ' , [role=article], [role=complementary], [role=navigation], [role=region]';\n\nconst getSectioningContentPlusMainSelector = (): string =>\n getSectioningContentSelector() + ' , main:not([role]), [role=main]';\n\nfunction hasAccessibleName(vNode: VNode, { checkTitle = false }: { checkTitle?: boolean } = {}): boolean {\n return !!(\n sanitize(arialabelledbyText(vNode)) ||\n sanitize(arialabelText(vNode)) ||\n (checkTitle && vNode?.props.nodeType === 1 && sanitize(vNode.attr('title') || ''))\n );\n}\n\ntype ImplicitRoleResolver = string | ((vNode: VNode) => string | null | undefined);\n\nexport const implicitHtmlRoles: Record<string, ImplicitRoleResolver> = {\n a: (vNode) => (vNode.hasAttr('href') ? 'link' : null),\n area: (vNode) => (vNode.hasAttr('href') ? 'link' : null),\n article: 'article',\n aside: (vNode) => {\n if (\n closest(vNode.parent, getSectioningContentSelector()) &&\n !hasAccessibleName(vNode, { checkTitle: true })\n ) {\n return null;\n }\n return 'complementary';\n },\n body: 'document',\n button: 'button',\n datalist: 'listbox',\n dd: 'definition',\n dfn: 'term',\n details: 'group',\n dialog: 'dialog',\n dt: 'term',\n fieldset: 'group',\n figure: 'figure',\n footer: (vNode) => {\n const sectioningElement = closest(vNode, getSectioningContentPlusMainSelector());\n return !sectioningElement ? 'contentinfo' : null;\n },\n form: (vNode) => (hasAccessibleName(vNode) ? 'form' : null),\n h1: 'heading',\n h2: 'heading',\n h3: 'heading',\n h4: 'heading',\n h5: 'heading',\n h6: 'heading',\n header: (vNode) => {\n const sectioningElement = closest(vNode, getSectioningContentPlusMainSelector());\n return !sectioningElement ? 'banner' : null;\n },\n hr: 'separator',\n img: (vNode) => {\n const emptyAlt = vNode.hasAttr('alt') && !vNode.attr('alt');\n const hasGlobalAria = getGlobalAriaAttrs().find((attr) => vNode.hasAttr(attr));\n return emptyAlt && !hasGlobalAria && !isFocusable(vNode) ? 'presentation' : 'img';\n },\n input: (vNode) => {\n let suggestionsSourceElement: boolean | undefined;\n if (vNode.hasAttr('list')) {\n const listElement = idrefs(vNode, 'list').filter((node) => !!node)[0];\n suggestionsSourceElement =\n !!listElement && (listElement as Element).nodeName.toLowerCase() === 'datalist';\n }\n switch (vNode.props.type) {\n case 'checkbox':\n return 'checkbox';\n case 'number':\n return 'spinbutton';\n case 'radio':\n return 'radio';\n case 'range':\n return 'slider';\n case 'search':\n return !suggestionsSourceElement ? 'searchbox' : 'combobox';\n case 'button':\n case 'image':\n case 'reset':\n case 'submit':\n return 'button';\n case 'text':\n case 'tel':\n case 'url':\n case 'email':\n case '':\n return !suggestionsSourceElement ? 'textbox' : 'combobox';\n default:\n return 'textbox';\n }\n },\n li: 'listitem',\n main: 'main',\n math: 'math',\n menu: 'list',\n meter: 'meter',\n nav: 'navigation',\n ol: 'list',\n optgroup: 'group',\n option: 'option',\n output: 'status',\n progress: 'progressbar',\n search: 'search',\n section: (vNode) => (hasAccessibleName(vNode) ? 'region' : null),\n select: (vNode) =>\n vNode.hasAttr('multiple') || parseInt(vNode.attr('size') || '', 10) > 1 ? 'listbox' : 'combobox',\n summary: 'button',\n table: 'table',\n tbody: 'rowgroup',\n td: (vNode) => {\n const table = closest(vNode, 'table');\n const role = table ? getExplicitRole(table) : null;\n return ['grid', 'treegrid'].includes(role as string) ? 'gridcell' : 'cell';\n },\n textarea: 'textbox',\n tfoot: 'rowgroup',\n th: (vNode) => {\n if (isColumnHeader(vNode)) return 'columnheader';\n if (isRowHeader(vNode)) return 'rowheader';\n return undefined;\n },\n thead: 'rowgroup',\n tr: 'row',\n ul: 'list',\n};\n","/**\n * Vendored axe-core `commons/aria` helpers, adapted to operate on real jsdom\n * DOM via the `VNode` wrapper. ARIA value lookups read attributes only (static\n * HTML has no AOM/ElementInternals); shadow DOM is ignored.\n */\nimport { ariaAttrs, ariaRoles } from './standards';\nimport {\n VNode,\n nodeLookup,\n getNodeFromTree,\n tokenList,\n isHtmlElement,\n getRootNode,\n type AnyNode,\n} from './core';\nimport { getGlobalAriaAttrs, getElementSpec, implicitHtmlRoles } from './stdhelpers';\n\n// ── role validity ────────────────────────────────────────────────\n\nexport function isUnsupportedRole(role: string | null): boolean {\n const roleDefinition = ariaRoles[role as string];\n return roleDefinition ? !!roleDefinition.unsupported : false;\n}\n\nexport function isValidRole(\n role: string | null,\n { allowAbstract, flagUnsupported = false }: { allowAbstract?: boolean; flagUnsupported?: boolean } = {},\n): boolean {\n const roleDefinition = ariaRoles[role as string];\n const isRoleUnsupported = isUnsupportedRole(role);\n if (!roleDefinition || (flagUnsupported && isRoleUnsupported)) return false;\n return allowAbstract ? true : roleDefinition.type !== 'abstract';\n}\n\nexport function getRoleType(role: string | VNode | null): string | null {\n if (role instanceof VNode) {\n role = getRole(role);\n }\n const roleDef = ariaRoles[role as string];\n return roleDef?.type || null;\n}\n\n// ── aria value access (attribute-only) ───────────────────────────\n\nexport function getAriaValue(\n node: VNode | AnyNode,\n attrName: string,\n options: { lowercase?: boolean } = {},\n): { value: string; source: string } | null {\n const attrStandard = ariaAttrs[attrName];\n if (!attrStandard) return null;\n const { type } = attrStandard;\n const { vNode } = nodeLookup(node);\n const { lowercase } = options;\n\n let value = vNode.attr(attrName);\n if (value === null || value === undefined) return null;\n if (type !== 'string') value = value.trim();\n if (lowercase) value = value.toLowerCase();\n return { value, source: 'attribute' };\n}\n\nexport function hasAriaValue(node: VNode | AnyNode, attrName: string): boolean {\n const attrStandard = ariaAttrs[attrName];\n if (!attrStandard) {\n throw new TypeError(`Attribute ${attrName} is not an ARIA attribute`);\n }\n const { vNode } = nodeLookup(node);\n return vNode.hasAttr(attrName);\n}\n\n// ── role resolution ──────────────────────────────────────────────\n\nexport function getExplicitRole(\n vNode: VNode | AnyNode,\n { fallback, abstracts, dpub }: { fallback?: boolean; abstracts?: boolean; dpub?: boolean } = {},\n): string | null {\n vNode = vNode instanceof VNode ? vNode : getNodeFromTree(vNode);\n if (vNode.props.nodeType !== 1) return null;\n\n const roleAttr = (vNode.attr('role') || '').trim().toLowerCase();\n const roleList = fallback ? tokenList(roleAttr) : [roleAttr];\n const firstValidRole = roleList.find((role) => {\n if (!dpub && role.substr(0, 4) === 'doc-') return false;\n return isValidRole(role, { allowAbstract: abstracts });\n });\n return firstValidRole || null;\n}\n\nexport function getImplicitRole(\n node: VNode | AnyNode,\n { chromium }: { chromium?: boolean } = {},\n): string | null {\n const { vNode } = nodeLookup(node);\n if (!vNode) {\n throw new ReferenceError('Cannot get implicit role of a node outside the current scope.');\n }\n const nodeName = vNode.props.nodeName;\n const role = implicitHtmlRoles[nodeName];\n if (!role && chromium) {\n const { chromiumRole } = getElementSpec(vNode) as { chromiumRole?: string };\n return chromiumRole || null;\n }\n if (typeof role === 'function') return role(vNode) ?? null;\n return (role as string) || null;\n}\n\nconst inheritsPresentationChain: Record<string, string[]> = {\n td: ['tr'],\n th: ['tr'],\n tr: ['thead', 'tbody', 'tfoot', 'table'],\n thead: ['table'],\n tbody: ['table'],\n tfoot: ['table'],\n li: ['ol', 'ul'],\n dt: ['dl', 'div'],\n dd: ['dl', 'div'],\n div: ['dl'],\n};\n\nfunction getInheritedRole(\n vNode: VNode,\n explicitRoleOptions: { fallback?: boolean; abstracts?: boolean; dpub?: boolean },\n): string | null {\n const parentNodeNames = inheritsPresentationChain[vNode.props.nodeName];\n if (!parentNodeNames) return null;\n if (!vNode.parent) {\n if (!vNode.actualNode) return null;\n throw new ReferenceError(\n 'Cannot determine role presentational inheritance of a required parent outside the current scope.',\n );\n }\n if (!parentNodeNames.includes(vNode.parent.props.nodeName)) return null;\n\n const parentRole = getExplicitRole(vNode.parent, explicitRoleOptions);\n if (['none', 'presentation'].includes(parentRole as string) && !hasConflictResolution(vNode.parent)) {\n return parentRole;\n }\n if (parentRole) return null;\n return getInheritedRole(vNode.parent, explicitRoleOptions);\n}\n\nfunction resolveImplicitRole(\n vNode: VNode,\n { chromium, ...explicitRoleOptions }: { chromium?: boolean; fallback?: boolean; abstracts?: boolean; dpub?: boolean },\n): string | null {\n const implicitRole = getImplicitRole(vNode, { chromium });\n if (!implicitRole) return null;\n const presentationalRole = getInheritedRole(vNode, explicitRoleOptions);\n if (presentationalRole) return presentationalRole;\n return implicitRole;\n}\n\nfunction hasConflictResolution(vNode: VNode): boolean {\n const hasGlobalAria = getGlobalAriaAttrs().some((attr) => vNode.hasAttr(attr));\n return hasGlobalAria || isFocusableRef(vNode);\n}\n\nfunction resolveRole(\n node: VNode | AnyNode,\n { noImplicit, ...roleOptions }: { noImplicit?: boolean; chromium?: boolean; fallback?: boolean; abstracts?: boolean; dpub?: boolean } = {},\n): string | null {\n const { vNode } = nodeLookup(node);\n if (vNode.props.nodeType !== 1) return null;\n const explicitRole = getExplicitRole(vNode, roleOptions);\n if (!explicitRole) {\n return noImplicit ? null : resolveImplicitRole(vNode, roleOptions);\n }\n if (!['presentation', 'none'].includes(explicitRole)) return explicitRole;\n if (hasConflictResolution(vNode)) {\n return noImplicit ? null : resolveImplicitRole(vNode, roleOptions);\n }\n return explicitRole;\n}\n\nexport function getRole(\n node: VNode | AnyNode,\n {\n noPresentational,\n ...options\n }: {\n noPresentational?: boolean;\n noImplicit?: boolean;\n chromium?: boolean;\n fallback?: boolean;\n abstracts?: boolean;\n dpub?: boolean;\n } = {},\n): string | null {\n const role = resolveRole(node, options);\n if (noPresentational && ['presentation', 'none'].includes(role as string)) return null;\n return role;\n}\n\nexport function namedFromContents(vNode: VNode | AnyNode, { strict }: { strict?: boolean } = {}): boolean {\n vNode = vNode instanceof VNode ? vNode : getNodeFromTree(vNode);\n if (vNode.props.nodeType !== 1) return false;\n const role = getRole(vNode);\n const roleDef = ariaRoles[role as string];\n if (roleDef && roleDef.nameFromContent) return true;\n if (strict) return false;\n return !roleDef || ['presentation', 'none'].includes(role as string);\n}\n\n// ── allowed / required attributes ────────────────────────────────\n\nexport function allowedAttr(role: string | null): string[] {\n const roleDef = ariaRoles[role as string];\n const attrs = [...getGlobalAriaAttrs()];\n if (!roleDef) return attrs;\n if (roleDef.allowedAttrs) attrs.push(...roleDef.allowedAttrs);\n if (roleDef.requiredAttrs) attrs.push(...roleDef.requiredAttrs);\n return attrs;\n}\n\nexport function requiredAttr(role: string | null): string[] {\n const roleDef = ariaRoles[role as string];\n if (!roleDef || !Array.isArray(roleDef.requiredAttrs)) return [];\n return [...roleDef.requiredAttrs];\n}\n\nexport function requiredContext(role: string | null): string[] | null {\n const roleDef = ariaRoles[role as string];\n if (!roleDef || !Array.isArray(roleDef.requiredContext)) return null;\n return [...roleDef.requiredContext];\n}\n\nexport function requiredOwned(role: string | null): string[] | null {\n const roleDef = ariaRoles[role as string];\n if (!roleDef || !Array.isArray(roleDef.requiredOwned)) return null;\n return [...roleDef.requiredOwned];\n}\n\nexport function validateAttr(att: string): boolean {\n return !!ariaAttrs[att];\n}\n\nexport function validateAttrValue(vNode: VNode | AnyNode, attr: string): boolean | undefined {\n vNode = vNode instanceof VNode ? vNode : getNodeFromTree(vNode);\n let m: RegExpMatchArray | null;\n let list: string[];\n const value = vNode.attr(attr);\n const attrInfo = ariaAttrs[attr];\n\n if (!attrInfo) return true;\n if (attrInfo.allowEmpty && (!value || value.trim() === '')) return true;\n\n switch (attrInfo.type) {\n case 'boolean':\n return ['true', 'false'].includes((value as string).toLowerCase());\n case 'nmtoken':\n return typeof value === 'string' && attrInfo.values.includes(value.toLowerCase());\n case 'nmtokens':\n list = tokenList(value as string);\n return list.reduce(\n (result: boolean, token: string) => result && attrInfo.values.includes(token),\n list.length !== 0,\n );\n case 'idref':\n try {\n const doc = getRootNode(vNode.actualNode) as unknown as { getElementById: (id: string) => Element | null };\n return !!(value && doc.getElementById(value));\n } catch {\n throw new TypeError('Cannot resolve id references for partial DOM');\n }\n case 'idrefs':\n return idrefs(vNode, attr).some((node) => !!node);\n case 'string':\n return (value as string).trim() !== '';\n case 'decimal':\n m = (value as string).match(/^[-+]?([0-9]*)\\.?([0-9]*)$/);\n return !!(m && (m[1] || m[2]));\n case 'int': {\n const minValue = typeof attrInfo.minValue !== 'undefined' ? attrInfo.minValue : -Infinity;\n return /^[-+]?[0-9]+$/.test(value as string) && parseInt(value as string, 10) >= minValue;\n }\n default:\n return undefined;\n }\n}\n\n// ── unallowed roles ──────────────────────────────────────────────\n\nconst dpubFallbackRoles = [\n 'doc-backlink', 'doc-biblioentry', 'doc-biblioref', 'doc-cover',\n 'doc-endnote', 'doc-glossref', 'doc-noteref',\n];\n\nconst landmarkRoles: Record<string, string> = { header: 'banner', footer: 'contentinfo' };\n\nfunction getRoleSegments(vNode: VNode | null): string[] {\n let roles: string[] = [];\n if (!vNode) return roles;\n if (vNode.hasAttr('role')) {\n const nodeRoles = tokenList((vNode.attr('role') || '').toLowerCase());\n roles = roles.concat(nodeRoles);\n }\n return roles.filter((role) => isValidRole(role));\n}\n\nexport function isAriaRoleAllowedOnElement(node: VNode | AnyNode, role: string): boolean {\n const vNode = node instanceof VNode ? node : getNodeFromTree(node);\n const implicitRole = getImplicitRole(vNode);\n const spec = getElementSpec(vNode) as { allowedRoles?: boolean | string[] };\n if (Array.isArray(spec.allowedRoles)) return spec.allowedRoles.includes(role);\n if (role === implicitRole) return false;\n return !!spec.allowedRoles;\n}\n\nexport function getElementUnallowedRoles(node: VNode | AnyNode, allowImplicit = true): string[] {\n const { vNode } = nodeLookup(node);\n if (!isHtmlElement(vNode)) return [];\n const { nodeName } = vNode.props;\n const implicitRole = getImplicitRole(vNode) || landmarkRoles[nodeName];\n const roleSegments = getRoleSegments(vNode);\n return roleSegments.filter((role) => !roleIsAllowed(role, vNode, allowImplicit, implicitRole));\n}\n\nfunction roleIsAllowed(role: string, vNode: VNode, allowImplicit: boolean, implicitRole: string | null): boolean {\n if (allowImplicit && role === implicitRole) return true;\n if (dpubFallbackRoles.includes(role) && getRoleType(role) !== implicitRole) return false;\n return isAriaRoleAllowedOnElement(vNode, role);\n}\n\n// ── owned virtual children ───────────────────────────────────────\n\nexport function getOwnedVirtual(virtualNode: VNode): VNode[] {\n const { children } = virtualNode;\n if (!children) throw new Error('getOwnedVirtual requires a virtual node');\n if (virtualNode.hasAttr('aria-owns')) {\n const owns = idrefs(virtualNode.actualNode, 'aria-owns')\n .filter((element) => !!element)\n .map((element) => getNodeFromTree(element as AnyNode));\n const uniqueOwns = owns.filter((own, index) => owns.indexOf(own) === index);\n const nativeChildren = children.filter((child) => !uniqueOwns.includes(child));\n return [...nativeChildren, ...uniqueOwns];\n }\n return [...children];\n}\n\n// ── accessible reference detection ───────────────────────────────\n\nconst idRefsRegex = /^idrefs?$/;\n\nfunction cacheIdRefs(node: AnyNode, idRefs: Map<string, AnyNode[]>, refAttrs: string[]): void {\n const el = node as unknown as {\n hasAttribute?: (n: string) => boolean;\n getAttribute?: (n: string) => string | null;\n nodeName: string;\n childNodes: ArrayLike<AnyNode>;\n };\n if (el.hasAttribute) {\n if (el.nodeName.toUpperCase() === 'LABEL' && el.hasAttribute('for')) {\n const id = el.getAttribute!('for') as string;\n if (!idRefs.has(id)) idRefs.set(id, [node]);\n else idRefs.get(id)!.push(node);\n }\n for (let i = 0; i < refAttrs.length; ++i) {\n const attr = refAttrs[i];\n const attrValue = sanitize(el.getAttribute!(attr) || '');\n if (!attrValue) continue;\n for (const token of tokenList(attrValue)) {\n if (!idRefs.has(token)) idRefs.set(token, [node]);\n else idRefs.get(token)!.push(node);\n }\n }\n }\n for (let i = 0; i < el.childNodes.length; i++) {\n if (el.childNodes[i].nodeType === 1) cacheIdRefs(el.childNodes[i], idRefs, refAttrs);\n }\n}\n\n// Per-document cache of id-ref maps (replaces axe's `cache`).\nconst idRefsByRoot = new WeakMap<object, Map<string, AnyNode[]>>();\n\nexport function getAccessibleRefs(node: VNode | AnyNode): AnyNode[] {\n const dom = (node instanceof VNode ? node.actualNode : node) as unknown as {\n id: string;\n documentElement?: AnyNode;\n };\n let root = getRootNode(dom as unknown as AnyNode) as unknown as { documentElement?: AnyNode };\n root = (root.documentElement || root) as unknown as { documentElement?: AnyNode };\n\n let idRefs = idRefsByRoot.get(root as unknown as object);\n if (!idRefs) {\n idRefs = new Map();\n idRefsByRoot.set(root as unknown as object, idRefs);\n const refAttrs = Object.keys(ariaAttrs).filter((attr) => {\n const { type } = ariaAttrs[attr];\n return idRefsRegex.test(type);\n });\n cacheIdRefs(root as unknown as AnyNode, idRefs, refAttrs);\n }\n return idRefs.get((dom as { id: string }).id) ?? [];\n}\n\nexport function isAccessibleRef(node: VNode | AnyNode): boolean {\n return !!getAccessibleRefs(node).length;\n}\n\n// ── ARIA label text ──────────────────────────────────────────────\n\nexport function arialabelText(element: VNode | AnyNode): string {\n const { vNode } = nodeLookup(element);\n if (vNode?.props.nodeType !== 1) return '';\n return vNode.attr('aria-label') || '';\n}\n\nexport function arialabelledbyText(\n element: VNode | AnyNode,\n context: { inLabelledByContext?: boolean; inControlContext?: boolean; startNode?: VNode } = {},\n): string {\n const { vNode } = nodeLookup(element);\n if (vNode?.props.nodeType !== 1) return '';\n if (\n vNode.props.nodeType !== 1 ||\n context.inLabelledByContext ||\n context.inControlContext ||\n !vNode.attr('aria-labelledby')\n ) {\n return '';\n }\n const refs = idrefs(vNode, 'aria-labelledby').filter((elm) => elm) as AnyNode[];\n return refs.reduce((accessibleName: string, elm) => {\n const accessibleNameAdd = accessibleText(elm, {\n inLabelledByContext: true,\n startNode: context.startNode || vNode,\n ...context,\n });\n if (!accessibleName) return accessibleNameAdd;\n return `${accessibleName} ${accessibleNameAdd}`;\n }, '');\n}\n\n// ── aria label (visible) ─────────────────────────────────────────\n\nexport function labelVirtual(virtualNode: VNode): string | null {\n let ref: AnyNode[];\n let candidate: string | null;\n\n if (virtualNode.attr('aria-labelledby')) {\n ref = idrefs(virtualNode.actualNode, 'aria-labelledby') as AnyNode[];\n candidate = ref\n .map((thing) => {\n const vNode = thing ? getNodeFromTree(thing) : null;\n return vNode ? visibleVirtual(vNode) : '';\n })\n .join(' ')\n .trim();\n if (candidate) return candidate;\n }\n\n candidate = virtualNode.attr('aria-label');\n if (candidate) {\n candidate = sanitize(candidate);\n if (candidate) return candidate;\n }\n return null;\n}\n\nexport function label(node: VNode | AnyNode): string | null {\n return labelVirtual(getNodeFromTree(node));\n}\n\n// ── combobox popup detection (for no-naming-method-matches) ──────\n\nconst isCombobox = (node: VNode): boolean => !!node && getRole(node) === 'combobox';\n\nfunction nearestParentWithRole(vNode: VNode): VNode | null {\n let v: VNode | null = vNode;\n while ((v = v.parent)) {\n if (getRole(v, { noPresentational: true }) !== null) return v;\n }\n return null;\n}\n\nexport function isComboboxPopup(virtualNode: VNode, { popupRoles }: { popupRoles?: string[] } = {}): boolean {\n const role = getRole(virtualNode);\n popupRoles ??= ariaAttrs['aria-haspopup'].values;\n if (!popupRoles!.includes(role as string)) return false;\n\n const vParent = nearestParentWithRole(virtualNode);\n if (vParent && isCombobox(vParent)) return true;\n\n const id = virtualNode.props.id;\n if (!id) return false;\n if (!virtualNode.actualNode) return false;\n\n const root = getRootNode(virtualNode.actualNode) as unknown as {\n querySelectorAll: (s: string) => ArrayLike<AnyNode>;\n };\n const ownedCombobox = Array.from(\n root.querySelectorAll(\n `[aria-owns~=\"${id}\"][role~=\"combobox\"]:not(select), [aria-controls~=\"${id}\"][role~=\"combobox\"]:not(select)`,\n ),\n );\n return ownedCombobox.some((n) => isCombobox(getNodeFromTree(n)));\n}\n\n// Lazy imports to break the aria↔dom↔text cycle at runtime.\nimport { idrefs, isFocusable as isFocusableRef } from './dom';\nimport { sanitize, accessibleText, visibleVirtual } from './text';\n","/**\n * Vendored axe-core check `evaluate` functions for the 26 supported rules,\n * adapted to operate on real DOM (`node`) plus the `VNode` wrapper\n * (`virtualNode`). Each returns axe's tri-state EXACTLY: `true` = pass,\n * `false` = fail, `undefined` = incomplete / needs review.\n */\nimport { ariaAttrs, ariaRoles } from './standards';\nimport {\n VNode,\n getNodeFromTree,\n tokenList,\n parseTabindex,\n uniqueArray,\n isHtmlElement,\n escapeSelector,\n getRootNode,\n closest,\n type AnyNode,\n} from './core';\nimport {\n getAriaValue,\n hasAriaValue,\n isValidRole,\n getRoleType,\n getRole,\n getExplicitRole,\n isUnsupportedRole,\n getElementUnallowedRoles,\n validateAttr,\n validateAttrValue,\n allowedAttr,\n requiredAttr,\n requiredOwned,\n requiredContext,\n getOwnedVirtual,\n arialabelText,\n arialabelledbyText,\n label,\n} from './aria';\nimport {\n isVisibleToScreenReaders,\n isVisibleOnScreen,\n isFocusable,\n isInTabOrder,\n getResolvedRefs,\n hasContent,\n hasContentVirtual,\n isHTML5,\n} from './dom';\nimport { getElementSpec, getGlobalAriaAttrs } from './stdhelpers';\nimport { sanitize, subtreeText, isValidAutocomplete, accessibleText, accessibleTextVirtual } from './text';\nimport * as tableUtils from './table';\n\n// Document context for the two checks that read `document` globally.\nlet currentDocument: Document;\nexport function setDocument(doc: Document): void {\n currentDocument = doc;\n}\n\n// ── check result builder ─────────────────────────────────────────\n\nexport class CheckBuilder {\n _data: unknown = null;\n _related: (VNode | AnyNode)[] = [];\n data(d: unknown): void {\n this._data = d;\n }\n relatedNodes(nodes: (VNode | AnyNode) | (VNode | AnyNode)[]): void {\n this._related = Array.isArray(nodes) ? nodes : [nodes];\n }\n}\n\ntype EvaluateFn = (this: CheckBuilder, node: AnyNode, options: Record<string, unknown>, virtualNode: VNode) => boolean | undefined;\ntype AfterFn = (results: { data: unknown; result: boolean | undefined }[]) => { data: unknown; result: boolean | undefined }[];\n\nexport interface CheckDef {\n evaluate: EvaluateFn;\n options?: Record<string, unknown>;\n after?: AfterFn;\n}\n\n// ── aria checks ──────────────────────────────────────────────────\n\nconst ariaHiddenBody: EvaluateFn = function (_node, _options, virtualNode) {\n return getAriaValue(virtualNode, 'aria-hidden', { lowercase: true })?.value !== 'true';\n};\n\nconst invalidrole: EvaluateFn = function (_node, _options, virtualNode) {\n const allRoles = tokenList(virtualNode.attr('role'));\n const allInvalid = allRoles.every((role) => !isValidRole(role.toLowerCase(), { allowAbstract: true }));\n if (allInvalid) {\n this.data(allRoles);\n return true;\n }\n return false;\n};\n\nconst abstractrole: EvaluateFn = function (_node, _options, virtualNode) {\n const abstractRoles = tokenList(virtualNode.attr('role')).filter((role) => getRoleType(role) === 'abstract');\n if (abstractRoles.length > 0) {\n this.data(abstractRoles);\n return true;\n }\n return false;\n};\n\nconst unsupportedrole: EvaluateFn = function (_node, _options, virtualNode) {\n const role = getRole(virtualNode, { dpub: true, fallback: true });\n const isUnsupported = isUnsupportedRole(role);\n if (isUnsupported) this.data(role);\n return isUnsupported;\n};\n\nconst deprecatedrole: EvaluateFn = function (_node, _options, virtualNode) {\n const role = getRole(virtualNode, { dpub: true, fallback: true });\n const roleDefinition = ariaRoles[role as string];\n if (!roleDefinition?.deprecated) return false;\n this.data(role);\n return true;\n};\n\nconst ariaAllowedRole: EvaluateFn = function (_node, options = {}, virtualNode) {\n const { allowImplicit = true, ignoredTags = [] } = options as { allowImplicit?: boolean; ignoredTags?: string[] };\n const { nodeName } = virtualNode.props;\n if (ignoredTags.map((tag) => tag.toLowerCase()).includes(nodeName)) return true;\n const unallowedRoles = getElementUnallowedRoles(virtualNode, allowImplicit);\n if (unallowedRoles.length) {\n this.data(unallowedRoles);\n if (!isVisibleToScreenReaders(virtualNode)) return undefined;\n return false;\n }\n return true;\n};\n\nconst ariaValidAttr: EvaluateFn = function (_node, options, virtualNode) {\n const opts = Array.isArray((options as { value?: unknown }).value) ? (options as { value: string[] }).value : [];\n const invalid: string[] = [];\n const aria = /^aria-/;\n virtualNode.attrNames.forEach((attr) => {\n if (opts.indexOf(attr) === -1 && aria.test(attr) && !validateAttr(attr)) invalid.push(attr);\n });\n if (invalid.length) {\n this.data(invalid);\n return false;\n }\n return true;\n};\n\nfunction isStringType(attrName: string): boolean {\n return ariaAttrs[attrName]?.type === 'string';\n}\n\nconst ariaValidAttrValue: EvaluateFn = function (_node, options, virtualNode) {\n const opts = Array.isArray((options as { value?: unknown }).value) ? (options as { value: string[] }).value : [];\n let needsReview = '';\n let messageKey = '';\n const invalid: string[] = [];\n const aria = /^aria-/;\n const skipAttrs = ['aria-errormessage'];\n\n const preChecks: Record<string, (validValue?: boolean) => boolean | void> = {\n 'aria-controls': () => {\n const hasPopup = !['false', null].includes(\n getAriaValue(virtualNode, 'aria-haspopup', { lowercase: true })?.value ?? null,\n );\n if (hasPopup) {\n needsReview = `aria-controls=\"${getAriaValue(virtualNode, 'aria-controls')?.value}\"`;\n messageKey = 'controlsWithinPopup';\n }\n return (\n getAriaValue(virtualNode, 'aria-expanded', { lowercase: true })?.value !== 'false' &&\n getAriaValue(virtualNode, 'aria-selected', { lowercase: true })?.value !== 'false' &&\n hasPopup === false\n );\n },\n 'aria-current': (validValue) => {\n if (!validValue) {\n needsReview = `aria-current=\"${getAriaValue(virtualNode, 'aria-current')?.value}\"`;\n messageKey = 'ariaCurrent';\n }\n return;\n },\n 'aria-owns': () => getAriaValue(virtualNode, 'aria-expanded', { lowercase: true })?.value !== 'false',\n 'aria-describedby': (validValue) => {\n if (!validValue) {\n needsReview = `aria-describedby=\"${getAriaValue(virtualNode, 'aria-describedby')?.value}\"`;\n messageKey = 'noId';\n }\n return;\n },\n 'aria-labelledby': (validValue) => {\n if (!validValue) {\n needsReview = `aria-labelledby=\"${getAriaValue(virtualNode, 'aria-labelledby')?.value}\"`;\n messageKey = 'noId';\n }\n },\n };\n\n virtualNode.attrNames.forEach((attrName) => {\n if (skipAttrs.includes(attrName) || opts.includes(attrName) || !aria.test(attrName)) return;\n let validValue: boolean | undefined;\n const attrValue = virtualNode.attr(attrName);\n try {\n validValue = validateAttrValue(virtualNode, attrName);\n } catch {\n needsReview = `${attrName}=\"${attrValue}\"`;\n messageKey = 'idrefs';\n return;\n }\n if ((preChecks[attrName] ? preChecks[attrName](validValue) : true) && !validValue) {\n if (attrValue === '' && !isStringType(attrName)) {\n needsReview = attrName;\n messageKey = 'empty';\n } else {\n invalid.push(`${attrName}=\"${attrValue}\"`);\n }\n }\n });\n\n if (invalid.length) {\n this.data(invalid);\n return false;\n }\n if (needsReview) {\n this.data({ messageKey, needsReview });\n return undefined;\n }\n return true;\n};\n\nconst ariaErrormessage: EvaluateFn = function (_node, options, virtualNode) {\n const opts = Array.isArray(options) ? (options as unknown as string[]) : [];\n const errorMessageAttr = getAriaValue(virtualNode, 'aria-errormessage')?.value;\n const hasAttr = hasAriaValue(virtualNode, 'aria-errormessage');\n const invalid = getAriaValue(virtualNode, 'aria-invalid', { lowercase: true })?.value;\n const hasInvalid = hasAriaValue(virtualNode, 'aria-invalid');\n if (!hasInvalid || invalid === 'false') return true;\n\n const validateAttrValueLocal = (attr: string): boolean | undefined => {\n if (attr.trim() === '') return ariaAttrs['aria-errormessage'].allowEmpty;\n const errormessageTokens = tokenList(attr);\n if (errormessageTokens.length > 1) {\n this.data({ messageKey: 'unsupported', values: errormessageTokens });\n return false;\n }\n let idref: VNode | null;\n try {\n idref = getResolvedRefs(virtualNode, 'aria-errormessage')[0] ?? null;\n } catch {\n this.data({ messageKey: 'idrefs', values: errormessageTokens });\n return undefined;\n }\n if (idref) {\n if (!isVisibleToScreenReaders(idref)) {\n this.data({ messageKey: 'hidden', values: errormessageTokens });\n return false;\n }\n const describedbyTokens = tokenList(getAriaValue(virtualNode, 'aria-describedby')?.value ?? '');\n return (\n getExplicitRole(idref) === 'alert' ||\n getAriaValue(idref, 'aria-live')?.value === 'assertive' ||\n getAriaValue(idref, 'aria-live')?.value === 'polite' ||\n errormessageTokens.some((token) => describedbyTokens.includes(token))\n );\n }\n return undefined;\n };\n\n if (opts.indexOf(errorMessageAttr as string) === -1 && hasAttr) {\n this.data(tokenList(errorMessageAttr as string));\n return validateAttrValueLocal(errorMessageAttr as string);\n }\n return true;\n};\n\nconst ariaLevel: EvaluateFn = function (_node, _options, virtualNode) {\n const ariaHeadingLevel = getAriaValue(virtualNode, 'aria-level')?.value;\n const ariaLevelValue = parseInt(ariaHeadingLevel as string, 10);\n if (ariaLevelValue > 6) return undefined;\n return true;\n};\n\nfunction ignoredAttrs(attrName: string, attrValue: string | null, vNode: VNode): boolean {\n if (attrName === 'aria-required' && attrValue === 'false') return true;\n if (attrName === 'aria-multiline' && attrValue === 'false' && vNode.hasAttr('contenteditable')) return true;\n return false;\n}\n\nconst ariaAllowedAttr: EvaluateFn = function (_node, options, virtualNode) {\n const invalid: string[] = [];\n const role = getRole(virtualNode);\n let allowed = allowedAttr(role);\n const opts = options as Record<string, unknown>;\n if (Array.isArray(opts[role as string])) {\n allowed = uniqueArray(opts[role as string] as string[], allowed);\n }\n for (const attrName of virtualNode.attrNames) {\n if (validateAttr(attrName) && !allowed.includes(attrName) && !ignoredAttrs(attrName, virtualNode.attr(attrName), virtualNode)) {\n invalid.push(attrName);\n }\n }\n if (!invalid.length) return true;\n this.data(invalid.map((attrName) => attrName + '=\"' + virtualNode.attr(attrName) + '\"'));\n if (!role && !isHtmlElement(virtualNode) && !isFocusable(virtualNode)) return undefined;\n return false;\n};\n\nconst ariaAllowedAttrElm: EvaluateFn = function (_node, _options, virtualNode) {\n const elmSpec = getElementSpec(virtualNode) as { allowedAriaAttrs?: string[] };\n if (!elmSpec.allowedAriaAttrs) return true;\n const explicitRole = getExplicitRole(virtualNode);\n if (explicitRole) return true;\n const { allowedAriaAttrs } = elmSpec;\n const globalAriaAttrs = getGlobalAriaAttrs();\n const invalid: string[] = [];\n for (const attrName of virtualNode.attrNames) {\n if (globalAriaAttrs.includes(attrName) && !allowedAriaAttrs.includes(attrName)) invalid.push(attrName);\n }\n if (!invalid.length) return true;\n this.data({ values: invalid });\n return false;\n};\n\nconst ariaUnsupportedAttr: EvaluateFn = function (_node, _options, virtualNode) {\n // No ARIA attribute in the standards table is marked unsupported, so this\n // always passes (faithful port — kept for the aria-allowed-attr rule's `none`).\n const unsupportedAttrs = virtualNode.attrNames.filter((name) => {\n const attribute = ariaAttrs[name];\n if (!validateAttr(name)) return false;\n const { unsupported } = attribute;\n if (typeof unsupported !== 'object') return !!unsupported;\n return false;\n });\n if (unsupportedAttrs.length) {\n this.data(unsupportedAttrs);\n return true;\n }\n return false;\n};\n\nfunction getClosestAncestorRoleType(vNode: VNode | null): string | undefined {\n if (!vNode) return undefined;\n const role = getRole(vNode, { noPresentational: true, chromium: true });\n if (role) return getRoleType(role) ?? undefined;\n return getClosestAncestorRoleType(vNode.parent);\n}\n\nfunction listProhibitedAttrs(vNode: VNode, role: string | null, nodeName: string, elementsAllowedAriaLabel: string[]): string[] {\n const roleSpec = ariaRoles[role as string];\n if (roleSpec) return roleSpec.prohibitedAttrs || [];\n if (!!role || elementsAllowedAriaLabel.includes(nodeName) || getClosestAncestorRoleType(vNode) === 'widget') {\n return [];\n }\n return ['aria-label', 'aria-labelledby'];\n}\n\nconst ariaProhibitedAttr: EvaluateFn = function (_node, options = {}, virtualNode) {\n const elementsAllowedAriaLabel = (options as { elementsAllowedAriaLabel?: string[] }).elementsAllowedAriaLabel || [];\n const { nodeName } = virtualNode.props;\n const role = getRole(virtualNode, { chromium: true, fallback: true });\n const prohibitedList = listProhibitedAttrs(virtualNode, role, nodeName, elementsAllowedAriaLabel);\n const prohibited = prohibitedList.filter((attrName) => {\n if (!virtualNode.attrNames.includes(attrName)) return false;\n return sanitize(virtualNode.attr(attrName)) !== '';\n });\n if (prohibited.length === 0) return false;\n let messageKey = role !== null ? 'hasRole' : 'noRole';\n messageKey += prohibited.length > 1 ? 'Plural' : 'Singular';\n this.data({ role, nodeName, messageKey, prohibited });\n const textContent = subtreeText(virtualNode, { subtreeDescendant: true });\n if (sanitize(textContent) !== '') return undefined;\n return true;\n};\n\nfunction hasImplicitAttr(elmSpec: { implicitAttrs?: Record<string, unknown> }, attr: string): boolean {\n return elmSpec.implicitAttrs?.[attr] !== undefined;\n}\nfunction isStaticSeparator(vNode: VNode, role: string | null): boolean {\n return role === 'separator' && !isFocusable(vNode);\n}\nfunction isClosedCombobox(vNode: VNode, role: string | null): boolean {\n return role === 'combobox' && getAriaValue(vNode, 'aria-expanded', { lowercase: true })?.value === 'false';\n}\n\nconst ariaRequiredAttr: EvaluateFn = function (_node, options = {}, virtualNode) {\n const role = getExplicitRole(virtualNode);\n const attrs = virtualNode.attrNames;\n let requiredAttrs = requiredAttr(role);\n const opts = options as Record<string, unknown>;\n if (Array.isArray(opts[role as string])) {\n requiredAttrs = uniqueArray(opts[role as string] as string[], requiredAttrs);\n }\n if (!role || !attrs.length || !requiredAttrs.length) return true;\n if (isStaticSeparator(virtualNode, role) || isClosedCombobox(virtualNode, role)) return true;\n if (role === 'slider' && getAriaValue(virtualNode, 'aria-valuetext')?.value) return true;\n const elmSpec = getElementSpec(virtualNode) as { implicitAttrs?: Record<string, unknown> };\n const missingAttrs = requiredAttrs.filter(\n (ra) => !getAriaValue(virtualNode, ra)?.value && !hasImplicitAttr(elmSpec, ra),\n );\n if (missingAttrs.length) {\n this.data(missingAttrs);\n return false;\n }\n return true;\n};\n\nfunction getGlobalAriaAttr(vNode: VNode): string | undefined {\n return getGlobalAriaAttrs().find((attr) => vNode.hasAttr(attr));\n}\n\nfunction getOwnedRoles(virtualNode: VNode, required: string[]): { role: string | null; attr?: string; vNode: VNode }[] {\n let vNode: VNode | undefined;\n const ownedRoles: { role: string | null; attr?: string; vNode: VNode }[] = [];\n const ownedVirtual = getOwnedVirtual(virtualNode);\n while ((vNode = ownedVirtual.shift())) {\n if (vNode.props.nodeType === 3) ownedRoles.push({ vNode, role: null });\n if (vNode.props.nodeType !== 1 || !isVisibleToScreenReaders(vNode)) continue;\n const role = getRole(vNode, { noPresentational: true });\n const globalAriaAttr = getGlobalAriaAttr(vNode);\n const hasGlobalAriaOrFocusable = !!globalAriaAttr || isFocusable(vNode);\n if (\n (!role && !hasGlobalAriaOrFocusable) ||\n (['group', 'rowgroup'].includes(role as string) && required.some((r) => r === role))\n ) {\n ownedVirtual.push(...vNode.children);\n } else if (role || hasGlobalAriaOrFocusable) {\n const attr = globalAriaAttr || (vNode.hasAttr('tabindex') ? 'tabindex' : undefined);\n ownedRoles.push({ role, attr, vNode });\n }\n }\n return ownedRoles;\n}\n\nfunction hasRequiredChildren(required: string[], ownedRoles: { role: string | null }[]): boolean {\n return ownedRoles.some(({ role }) => role && required.includes(role));\n}\n\nfunction getUnallowedSelector(vNode: VNode, attr?: string): string {\n const { nodeName, nodeType } = vNode.props;\n if (nodeType === 3) return `#text`;\n const role = getExplicitRole(vNode, { dpub: true });\n if (role) return `[role=${role}]`;\n if (attr) return nodeName + `[${attr}]`;\n return nodeName;\n}\n\nfunction isContentOwned({ vNode }: { vNode: VNode }): boolean {\n if (vNode.props.nodeType === 3) return (vNode.props.nodeValue || '').trim().length > 0;\n return hasContentVirtual(vNode, false, true);\n}\n\nconst ariaRequiredChildren: EvaluateFn = function (_node, options, virtualNode) {\n const reviewEmpty = options && Array.isArray((options as { reviewEmpty?: unknown }).reviewEmpty)\n ? (options as { reviewEmpty: string[] }).reviewEmpty\n : [];\n const explicitRole = getExplicitRole(virtualNode, { dpub: true });\n const required = requiredOwned(explicitRole);\n if (required === null) return true;\n\n const ownedRoles = getOwnedRoles(virtualNode, required);\n const unallowed = ownedRoles.filter(({ role, vNode }) => vNode.props.nodeType === 1 && !required.includes(role as string));\n\n if (unallowed.length) {\n this.relatedNodes(unallowed.map(({ vNode }) => vNode));\n const messageKey = getAriaValue(virtualNode, 'aria-busy')?.value === 'true' ? 'aria-busy-fail' : 'unallowed';\n this.data({\n messageKey,\n values: unallowed\n .map(({ vNode, attr }) => getUnallowedSelector(vNode, attr))\n .filter((selector, index, array) => array.indexOf(selector) === index)\n .join(', '),\n });\n return false;\n }\n if (hasRequiredChildren(required, ownedRoles)) return true;\n if (getAriaValue(virtualNode, 'aria-busy')?.value === 'true') {\n this.data({ messageKey: 'aria-busy' });\n return true;\n }\n this.data(required);\n if (reviewEmpty.includes(explicitRole as string) && !ownedRoles.some(isContentOwned)) return undefined;\n return false;\n};\n\nfunction getMissingContext(\n virtualNode: VNode,\n ownGroupRoles: string[],\n reqContext: string[] | null,\n includeElement?: boolean,\n): string[] | null {\n const explicitRole = getExplicitRole(virtualNode);\n if (!reqContext) reqContext = requiredContext(explicitRole);\n if (!reqContext) return null;\n const allowsGroup = reqContext.includes('group');\n let vNode: VNode | null = includeElement ? virtualNode : virtualNode.parent;\n while (vNode) {\n const role = getRole(vNode, { noPresentational: true });\n if (!role) {\n vNode = vNode.parent;\n } else if (role === 'group' && allowsGroup) {\n if (ownGroupRoles.includes(explicitRole as string)) reqContext.push(explicitRole as string);\n reqContext = reqContext.filter((r) => r !== 'group');\n vNode = vNode.parent;\n } else if (reqContext.includes(role)) {\n return null;\n } else {\n return reqContext;\n }\n }\n return reqContext;\n}\n\n// Per-document reverse index of `aria-owns`: referenced id → owning elements.\n// Built once by scanning every `[aria-owns]` element, then reused for the whole\n// document (keyed by root node, scoped per scan). The previous implementation\n// ran a full-document `querySelector('[aria-owns~=id]')` for *every* ancestor of\n// *every* aria-required-parent candidate; in jsdom (JS `querySelector`, not\n// native) that went quadratic and froze scans at 40% \"Analyzing pages\" on large\n// storefronts (~40s for one 8k-node page). Index lookups make it linear.\nconst ariaOwnsIndexByRoot = new WeakMap<object, Map<string, AnyNode[]>>();\n\nfunction getAriaOwnsIndex(root: AnyNode): Map<string, AnyNode[]> {\n const cached = ariaOwnsIndexByRoot.get(root as unknown as object);\n if (cached) return cached;\n const idx = new Map<string, AnyNode[]>();\n ariaOwnsIndexByRoot.set(root as unknown as object, idx);\n const scope = root as unknown as { querySelectorAll?: (s: string) => ArrayLike<AnyNode> };\n const owners = scope.querySelectorAll ? Array.from(scope.querySelectorAll('[aria-owns]')) : [];\n for (const owner of owners) {\n const val = (owner as unknown as { getAttribute: (a: string) => string | null }).getAttribute('aria-owns') || '';\n // `[aria-owns~=id]` matches whitespace-separated tokens — tokenize the same way.\n for (const token of val.split(/\\s+/)) {\n if (!token) continue;\n const list = idx.get(token);\n if (list) list.push(owner);\n else idx.set(token, [owner]);\n }\n }\n return idx;\n}\n\nfunction getAriaOwners(element: AnyNode): AnyNode[] | null {\n const idx = getAriaOwnsIndex(getRootNode(element));\n if (idx.size === 0) return null; // no `aria-owns` anywhere → nothing can own this subtree\n const owners: AnyNode[] = [];\n let el: { getAttribute?: (a: string) => string | null; parentElement?: AnyNode | null } | null =\n element as unknown as { getAttribute?: (a: string) => string | null; parentElement?: AnyNode | null };\n while (el) {\n const id = el.getAttribute ? el.getAttribute('id') : null;\n if (id) {\n // Preserve prior single-match semantics (`querySelector` → first owner).\n const found = idx.get(id);\n if (found && found[0]) owners.push(found[0]);\n }\n el = (el as { parentElement?: AnyNode | null }).parentElement as never;\n }\n return owners.length ? owners : null;\n}\n\nconst ariaRequiredParent: EvaluateFn = function (node, options, virtualNode) {\n const ownGroupRoles = options && Array.isArray((options as { ownGroupRoles?: unknown }).ownGroupRoles)\n ? (options as { ownGroupRoles: string[] }).ownGroupRoles\n : [];\n let missingParents = getMissingContext(virtualNode, ownGroupRoles, null);\n if (!missingParents) return true;\n const owners = getAriaOwners(node);\n if (owners) {\n for (let i = 0, l = owners.length; i < l; i++) {\n missingParents = getMissingContext(getNodeFromTree(owners[i]), ownGroupRoles, missingParents, true);\n if (!missingParents) return true;\n }\n }\n this.data(missingParents);\n return false;\n};\n\nconst hasGlobalAriaAttribute: EvaluateFn = function (_node, _options, virtualNode) {\n const globalAttrs = getGlobalAriaAttrs().filter((attr) => virtualNode.hasAttr(attr));\n this.data(globalAttrs);\n return globalAttrs.length > 0;\n};\n\nconst isElementFocusable: EvaluateFn = function (_node, _options, virtualNode) {\n return isFocusable(virtualNode);\n};\n\n// ── parsing ──────────────────────────────────────────────────────\n\nconst duplicateId: EvaluateFn = function (node) {\n const id = ((node as unknown as { getAttribute: (a: string) => string }).getAttribute('id') || '').trim();\n if (!id) return true;\n const root = getRootNode(node) as unknown as { querySelectorAll: (s: string) => ArrayLike<AnyNode> };\n const matchingNodes = Array.from(root.querySelectorAll(`[id=\"${escapeSelector(id)}\"]`)).filter(\n (foundNode) => foundNode !== node,\n );\n if (matchingNodes.length) this.relatedNodes(matchingNodes);\n this.data(id);\n return matchingNodes.length === 0;\n};\n\nconst duplicateIdAfter: AfterFn = function (results) {\n const uniqueIds: unknown[] = [];\n return results.filter((r) => {\n if (uniqueIds.indexOf(r.data) === -1) {\n uniqueIds.push(r.data);\n return true;\n }\n return false;\n });\n};\n\n// ── forms ────────────────────────────────────────────────────────\n\nconst autocompleteValid: EvaluateFn = function (_node, options, virtualNode) {\n const autocomplete = virtualNode.attr('autocomplete') || '';\n return isValidAutocomplete(autocomplete, options as Record<string, never>);\n};\n\n// ── keyboard ─────────────────────────────────────────────────────\n\nfunction usesUnreliableHidingStrategy(vNode: VNode): boolean {\n const tabIndex = parseTabindex(vNode.attr('tabindex'));\n return tabIndex !== null && tabIndex < 0;\n}\n\nfunction getFocusableDescendants(vNode: VNode): VNode[] {\n if (!vNode.children) {\n if (vNode.props.nodeType === 1) throw new Error('Cannot determine children');\n return [];\n }\n const retVal: VNode[] = [];\n vNode.children.forEach((child) => {\n if (getRoleType(child) === 'widget' && isFocusable(child)) retVal.push(child);\n else retVal.push(...getFocusableDescendants(child));\n });\n return retVal;\n}\n\nconst noFocusableContent: EvaluateFn = function (_node, _options, virtualNode) {\n if (!virtualNode.children) return undefined;\n try {\n const focusableDescendants = getFocusableDescendants(virtualNode);\n if (!focusableDescendants.length) return true;\n const notHiddenElements = focusableDescendants.filter(usesUnreliableHidingStrategy);\n if (notHiddenElements.length > 0) {\n this.data({ messageKey: 'notHidden' });\n this.relatedNodes(notHiddenElements);\n } else {\n this.relatedNodes(focusableDescendants);\n }\n return false;\n } catch {\n return undefined;\n }\n};\n\nconst tabindexCheck: EvaluateFn = function (_node, _options, virtualNode) {\n const tabIndex = parseTabindex(virtualNode.attr('tabindex'));\n return tabIndex === null || tabIndex <= 0;\n};\n\n// ── tables ───────────────────────────────────────────────────────\n\nconst tdHasHeader: EvaluateFn = function (node) {\n const badCells: AnyNode[] = [];\n const cells = tableUtils.getAllCells(node as never);\n const tableGrid = tableUtils.toGrid(node as never);\n cells.forEach((cell) => {\n if (hasContent(cell) && tableUtils.isDataCell(cell) && !label(cell)) {\n const hasHeaders = tableUtils.getHeaders(cell, tableGrid).some((header) => header !== null && !!hasContent(header));\n if (!hasHeaders) badCells.push(cell);\n }\n });\n if (badCells.length) {\n this.relatedNodes(badCells);\n return false;\n }\n return true;\n};\n\nconst thHasDataCells: EvaluateFn = function (node) {\n const cells = tableUtils.getAllCells(node as never);\n let reffedHeaders: string[] = [];\n cells.forEach((cell) => {\n const headers = (cell as unknown as { getAttribute: (a: string) => string | null }).getAttribute('headers');\n if (headers) reffedHeaders = reffedHeaders.concat(headers.split(/\\s+/));\n const ariaLabel = (cell as unknown as { getAttribute: (a: string) => string | null }).getAttribute('aria-labelledby');\n if (ariaLabel) reffedHeaders = reffedHeaders.concat(ariaLabel.split(/\\s+/));\n });\n const headers = cells.filter((cell) => {\n if (sanitize((cell as unknown as { textContent: string }).textContent) === '') return false;\n return (\n (cell as unknown as { nodeName: string }).nodeName.toUpperCase() === 'TH' ||\n ['rowheader', 'columnheader'].indexOf(getExplicitRole(cell) as string) !== -1\n );\n });\n const tableGrid = tableUtils.toGrid(node as never);\n let out: boolean = true;\n headers.forEach((header) => {\n const h = header as unknown as { getAttribute: (a: string) => string | null };\n if (h.getAttribute('id') && reffedHeaders.includes(h.getAttribute('id') as string)) return;\n const pos = tableUtils.getCellPosition(header, tableGrid)!;\n let hasCell: unknown = false;\n if (tableUtils.isColumnHeader(header)) {\n hasCell = tableUtils\n .traverse('down', pos, tableGrid)\n .find((cell) => !tableUtils.isColumnHeader(cell) && tableUtils.getHeaders(cell, tableGrid).includes(header));\n }\n if (!hasCell && tableUtils.isRowHeader(header)) {\n hasCell = tableUtils\n .traverse('right', pos, tableGrid)\n .find((cell) => !tableUtils.isRowHeader(cell) && tableUtils.getHeaders(cell, tableGrid).includes(header));\n }\n if (!hasCell) this.relatedNodes(header);\n out = out && !!hasCell;\n });\n return out ? true : undefined;\n};\n\nconst tdHeadersAttrMessageKeys = ['cell-header-not-in-table', 'cell-header-not-th', 'header-refs-self', 'empty-hdrs'];\nconst tdHeadersAttr: EvaluateFn = function (node) {\n const [notInTable, notTh, selfRef, emptyHdrs] = tdHeadersAttrMessageKeys;\n const tableNode = node as unknown as { rows: ArrayLike<{ cells: ArrayLike<AnyNode> }> };\n const cells: AnyNode[] = [];\n const cellRoleById: Record<string, string | null> = {};\n for (let rowIndex = 0; rowIndex < tableNode.rows.length; rowIndex++) {\n const row = tableNode.rows[rowIndex];\n for (let cellIndex = 0; cellIndex < row.cells.length; cellIndex++) {\n const cell = row.cells[cellIndex];\n cells.push(cell);\n const cellId = (cell as unknown as { getAttribute: (a: string) => string | null }).getAttribute('id');\n if (cellId) cellRoleById[cellId] = getRole(cell);\n }\n }\n const badCells: Record<string, Set<AnyNode>> = {\n [selfRef]: new Set(),\n [notInTable]: new Set(),\n [notTh]: new Set(),\n [emptyHdrs]: new Set(),\n };\n cells.forEach((cell) => {\n const c = cell as unknown as { hasAttribute: (a: string) => boolean; getAttribute: (a: string) => string | null };\n if (!c.hasAttribute('headers') || !isVisibleToScreenReaders(cell)) return;\n const headersAttr = (c.getAttribute('headers') || '').trim();\n if (!headersAttr) {\n badCells[emptyHdrs].add(cell);\n return;\n }\n const cellId = c.getAttribute('id');\n const headers = tokenList(headersAttr);\n headers.forEach((headerId) => {\n if (cellId && headerId === cellId) badCells[selfRef].add(cell);\n else if (!cellRoleById[headerId]) badCells[notInTable].add(cell);\n else if (!['columnheader', 'rowheader'].includes(cellRoleById[headerId] as string)) badCells[notTh].add(cell);\n });\n });\n for (const messageKey of tdHeadersAttrMessageKeys) {\n if (badCells[messageKey].size > 0) {\n this.relatedNodes([...badCells[messageKey]]);\n if (messageKey === emptyHdrs) return undefined;\n this.data({ messageKey });\n return false;\n }\n }\n return true;\n};\n\nconst html5Scope: EvaluateFn = function (node) {\n if (!isHTML5(currentDocument)) return true;\n return (node as unknown as { nodeName: string }).nodeName.toUpperCase() === 'TH';\n};\n\nconst scopeValue: EvaluateFn = function (node, options) {\n const value = ((node as unknown as { getAttribute: (a: string) => string }).getAttribute('scope') || '').toLowerCase();\n return (options as { values: string[] }).values.indexOf(value) !== -1;\n};\n\n// ── shared ───────────────────────────────────────────────────────\n\nconst docHasTitle: EvaluateFn = function () {\n const title = currentDocument.title;\n return !!sanitize(title);\n};\n\nconst attrNonSpaceContent: EvaluateFn = function (_node, options = {}, vNode) {\n const attribute = (options as { attribute?: string }).attribute;\n if (!attribute || typeof attribute !== 'string') {\n throw new TypeError('attr-non-space-content requires options.attribute to be a string');\n }\n if (!vNode.hasAttr(attribute)) {\n this.data({ messageKey: 'noAttr' });\n return false;\n }\n if (!sanitize(vNode.attr(attribute))) {\n this.data({ messageKey: 'emptyAttr' });\n return false;\n }\n return true;\n};\n\nconst ariaLabelCheck: EvaluateFn = function (_node, _options, virtualNode) {\n return !!sanitize(arialabelText(virtualNode));\n};\n\nconst ariaLabelledbyCheck: EvaluateFn = function (_node, _options, virtualNode) {\n try {\n return !!sanitize(arialabelledbyText(virtualNode));\n } catch {\n return undefined;\n }\n};\n\nconst presentationalRole: EvaluateFn = function (_node, _options, virtualNode) {\n const explicitRole = getExplicitRole(virtualNode);\n if (\n ['presentation', 'none'].includes(explicitRole as string) &&\n ['iframe', 'frame'].includes(virtualNode.props.nodeName) &&\n virtualNode.hasAttr('title')\n ) {\n this.data({ messageKey: 'iframe', nodeName: virtualNode.props.nodeName });\n return false;\n }\n const role = getRole(virtualNode);\n if (['presentation', 'none'].includes(role as string)) {\n this.data({ role });\n return true;\n }\n if (!['presentation', 'none'].includes(explicitRole as string)) return false;\n const hasGlobalAria = getGlobalAriaAttrs().some((attr) => virtualNode.hasAttr(attr));\n const focusable = isFocusable(virtualNode);\n let messageKey: string;\n if (hasGlobalAria && !focusable) messageKey = 'globalAria';\n else if (!hasGlobalAria && focusable) messageKey = 'focusable';\n else messageKey = 'both';\n this.data({ messageKey, role });\n return false;\n};\n\nconst isOnScreen: EvaluateFn = function (node) {\n return isVisibleOnScreen(node);\n};\n\n// ── navigation ───────────────────────────────────────────────────\n\nconst uniqueFrameTitle: EvaluateFn = function (_node, _options, vNode) {\n const title = sanitize(vNode.attr('title')).toLowerCase();\n this.data(title);\n return true;\n};\n\nconst uniqueFrameTitleAfter: AfterFn = function (results) {\n const titles: Record<string, number> = {};\n results.forEach((r) => {\n const key = r.data as string;\n titles[key] = titles[key] !== undefined ? ++titles[key] : 0;\n });\n results.forEach((r) => {\n r.result = !!titles[r.data as string];\n });\n return results;\n};\n\nconst separatorRegex = /[;,\\s]/;\nconst validRedirectNumRegex = /^[0-9.]+$/;\nconst metaRefresh: EvaluateFn = function (_node, options, virtualNode) {\n const { minDelay, maxDelay } = (options || {}) as { minDelay?: number; maxDelay?: number };\n const content = (virtualNode.attr('content') || '').trim();\n const [redirectStr] = content.split(separatorRegex);\n if (!redirectStr.match(validRedirectNumRegex)) return true;\n const redirectDelay = parseFloat(redirectStr);\n this.data({ redirectDelay });\n if (typeof minDelay === 'number' && redirectDelay <= minDelay) return true;\n if (typeof maxDelay === 'number' && redirectDelay > maxDelay) return true;\n return false;\n};\n\n// ── name/label/landmark checks (button-name, link-name, label, etc.) ─\n\nconst hasTextContent: EvaluateFn = function (_node, _options, virtualNode) {\n try {\n return sanitize(subtreeText(virtualNode)) !== '';\n } catch {\n return undefined;\n }\n};\n\nconst focusableNoName: EvaluateFn = function (_node, _options, virtualNode) {\n if (!isInTabOrder(virtualNode)) return false;\n try {\n return !accessibleTextVirtual(virtualNode);\n } catch {\n return undefined;\n }\n};\n\nconst implicitLabel: EvaluateFn = function (_node, _options, virtualNode) {\n try {\n const labelNode = closest(virtualNode, 'label');\n if (labelNode) {\n const implicit = sanitize(\n accessibleTextVirtual(labelNode, { inControlContext: true, startNode: virtualNode }),\n );\n if (labelNode.actualNode) this.relatedNodes([labelNode]);\n this.data({ implicitLabel: implicit });\n return !!implicit;\n }\n return false;\n } catch {\n return undefined;\n }\n};\n\nconst explicitLabel: EvaluateFn = function (_node, _options, virtualNode) {\n if (!virtualNode.attr('id')) return false;\n if (!virtualNode.actualNode) return undefined;\n const root = getRootNode(virtualNode.actualNode) as unknown as {\n querySelectorAll: (s: string) => ArrayLike<AnyNode>;\n };\n const id = escapeSelector(virtualNode.attr('id') as string);\n const labels = Array.from(root.querySelectorAll(`label[for=\"${id}\"]`));\n this.relatedNodes(labels);\n if (!labels.length) return false;\n try {\n return labels.some((labelNode) => {\n if (!isVisibleOnScreen(labelNode)) return true;\n const explicit = sanitize(\n accessibleText(labelNode, { inControlContext: true, startNode: virtualNode }),\n );\n this.data({ explicitLabel: explicit });\n return !!explicit;\n });\n } catch {\n return undefined;\n }\n};\n\nconst hiddenExplicitLabel: EvaluateFn = function (node, _options, virtualNode) {\n if (virtualNode.hasAttr('id')) {\n if (!virtualNode.actualNode) return undefined;\n const root = getRootNode(node) as unknown as { querySelector: (s: string) => AnyNode | null };\n const id = escapeSelector((node as unknown as { getAttribute: (a: string) => string }).getAttribute('id'));\n const labelNode = root.querySelector(`label[for=\"${id}\"]`);\n if (labelNode && !isVisibleToScreenReaders(labelNode)) {\n let name: string;\n try {\n name = accessibleTextVirtual(virtualNode).trim();\n } catch {\n return undefined;\n }\n return name === '';\n }\n }\n return false;\n};\n\nconst landmarkIsUnique: EvaluateFn = function (node, _options, virtualNode) {\n const role = getRole(node);\n let accText: string | null = accessibleTextVirtual(virtualNode);\n accText = accText ? accText.toLowerCase() : null;\n this.data({ role, accessibleText: accText });\n this.relatedNodes([virtualNode]);\n return true;\n};\n\nconst landmarkIsUniqueAfter: AfterFn = function (results) {\n const uniqueLandmarks: { data: unknown; result: boolean | undefined }[] = [];\n return results.filter((currentResult) => {\n const cur = currentResult.data as { role: string | null; accessibleText: string | null };\n const matched = uniqueLandmarks.find((some) => {\n const s = some.data as { role: string | null; accessibleText: string | null };\n return cur.role === s.role && cur.accessibleText === s.accessibleText;\n });\n if (matched) {\n matched.result = false;\n return false;\n }\n uniqueLandmarks.push(currentResult);\n return true;\n });\n};\n\n// ── registry ─────────────────────────────────────────────────────\n\nexport const checks: Record<string, CheckDef> = {\n 'button-has-visible-text': { evaluate: hasTextContent },\n 'has-visible-text': { evaluate: hasTextContent },\n 'non-empty-placeholder': { evaluate: attrNonSpaceContent, options: { attribute: 'placeholder' } },\n 'focusable-no-name': { evaluate: focusableNoName },\n 'implicit-label': { evaluate: implicitLabel },\n 'explicit-label': { evaluate: explicitLabel },\n 'hidden-explicit-label': { evaluate: hiddenExplicitLabel },\n 'landmark-is-unique': { evaluate: landmarkIsUnique, after: landmarkIsUniqueAfter },\n 'aria-hidden-body': { evaluate: ariaHiddenBody },\n invalidrole: { evaluate: invalidrole },\n abstractrole: { evaluate: abstractrole },\n unsupportedrole: { evaluate: unsupportedrole },\n deprecatedrole: { evaluate: deprecatedrole },\n 'aria-allowed-role': { evaluate: ariaAllowedRole, options: { allowImplicit: true, ignoredTags: [] } },\n 'aria-valid-attr': { evaluate: ariaValidAttr },\n 'aria-valid-attr-value': { evaluate: ariaValidAttrValue },\n 'aria-errormessage': { evaluate: ariaErrormessage },\n 'aria-level': { evaluate: ariaLevel },\n 'aria-allowed-attr': {\n evaluate: ariaAllowedAttr,\n options: { validTreeRowAttrs: ['aria-posinset', 'aria-setsize', 'aria-expanded', 'aria-level'] },\n },\n 'aria-allowed-attr-elm': { evaluate: ariaAllowedAttrElm },\n 'aria-unsupported-attr': { evaluate: ariaUnsupportedAttr },\n 'aria-prohibited-attr': { evaluate: ariaProhibitedAttr, options: { elementsAllowedAriaLabel: ['applet', 'input'] } },\n 'aria-required-attr': { evaluate: ariaRequiredAttr },\n 'aria-required-children': {\n evaluate: ariaRequiredChildren,\n options: {\n reviewEmpty: [\n 'doc-bibliography', 'doc-endnotes', 'grid', 'list', 'listbox', 'menu',\n 'menubar', 'table', 'tablist', 'tree', 'treegrid', 'rowgroup',\n ],\n },\n },\n 'aria-required-parent': { evaluate: ariaRequiredParent, options: { ownGroupRoles: ['listitem', 'treeitem'] } },\n 'has-global-aria-attribute': { evaluate: hasGlobalAriaAttribute },\n 'is-element-focusable': { evaluate: isElementFocusable },\n 'duplicate-id-aria': { evaluate: duplicateId, after: duplicateIdAfter },\n 'autocomplete-valid': {\n evaluate: autocompleteValid,\n options: {\n stateTerms: ['none', 'false', 'true', 'disabled', 'enabled', 'undefined', 'null', 'xoff', 'xon'],\n ignoredValues: ['text', 'pronouns', 'gender', 'message', 'content'],\n },\n },\n 'no-focusable-content': { evaluate: noFocusableContent },\n tabindex: { evaluate: tabindexCheck },\n 'td-has-header': { evaluate: tdHasHeader },\n 'th-has-data-cells': { evaluate: thHasDataCells },\n 'td-headers-attr': { evaluate: tdHeadersAttr },\n 'html5-scope': { evaluate: html5Scope },\n 'scope-value': { evaluate: scopeValue, options: { values: ['row', 'col', 'rowgroup', 'colgroup'] } },\n 'doc-has-title': { evaluate: docHasTitle },\n 'non-empty-title': { evaluate: attrNonSpaceContent, options: { attribute: 'title' } },\n 'aria-label': { evaluate: ariaLabelCheck },\n 'aria-labelledby': { evaluate: ariaLabelledbyCheck },\n 'presentational-role': { evaluate: presentationalRole },\n 'is-on-screen': { evaluate: isOnScreen },\n 'unique-frame-title': { evaluate: uniqueFrameTitle, after: uniqueFrameTitleAfter },\n 'meta-refresh': { evaluate: metaRefresh, options: { minDelay: 0, maxDelay: 72000 } },\n};\n","/**\n * The 26 supported axe rules and the rule runner.\n *\n * Per rule we: select candidate elements, filter by the rule `matches` predicate\n * and (unless `excludeHidden:false`) by screen-reader visibility, evaluate the\n * all/any/none check composition per node, apply any `after` reducer, then\n * collapse to a single rule-level status with failing-node targets.\n */\nimport { ariaRoles } from './standards';\nimport { VNode, toVNode, parseTabindex, registerMatchers, type AnyNode } from './core';\nimport {\n getExplicitRole,\n getImplicitRole,\n getRole,\n requiredOwned,\n requiredContext,\n isAccessibleRef,\n isComboboxPopup,\n} from './aria';\nimport { isVisibleToScreenReaders, isVisibleOnScreen, isFocusable, querySelectorAll } from './dom';\nimport { getElementSpec, getAriaRolesByType } from './stdhelpers';\nimport { sanitize, accessibleTextVirtual } from './text';\nimport { isDataTable, toArray } from './table';\nimport { checks, setDocument, CheckBuilder, type CheckDef } from './checks';\n\n// Wire role-based matchers into the core `matches()` used by getElementSpec.\nregisterMatchers({\n getExplicitRole: (v) => getExplicitRole(v),\n getImplicitRole: (v) => getImplicitRole(v),\n getRole: (v) => getRole(v),\n accessibleTextVirtual: (v) => accessibleTextVirtual(v),\n});\n\nexport type AxeStatus = 'pass' | 'fail' | 'incomplete' | 'inapplicable';\n\n// ── matches predicates ───────────────────────────────────────────\n\ntype MatchFn = (node: AnyNode, vNode: VNode) => boolean;\n\nconst isInitiator: MatchFn = () => true; // we only scan top-level documents\n\nconst noEmptyRole: MatchFn = (_node, vNode) => {\n if (!vNode.hasAttr('role')) return false;\n if (!(vNode.attr('role') || '').trim()) return false;\n return true;\n};\n\nconst ariaAllowedRoleMatch: MatchFn = (_node, vNode) =>\n getExplicitRole(vNode, { dpub: true, fallback: true }) !== null;\n\nconst ariaHasAttr: MatchFn = (_node, vNode) => vNode.attrNames.some((attr) => attr.startsWith('aria-'));\n\nconst ariaRequiredChildrenMatch: MatchFn = (_node, vNode) =>\n !!requiredOwned(getExplicitRole(vNode, { dpub: true }));\n\nconst ariaRequiredParentMatch: MatchFn = (_node, vNode) =>\n !!requiredContext(getExplicitRole(vNode));\n\nconst duplicateIdAriaMatch: MatchFn = (node) => isAccessibleRef(node);\n\nconst autocompleteMatch: MatchFn = (_node, vNode) => {\n const autocomplete = vNode.attr('autocomplete');\n if (!autocomplete || sanitize(autocomplete) === '') return false;\n const nodeName = vNode.props.nodeName;\n if (['textarea', 'input', 'select'].includes(nodeName) === false) return false;\n const ariaReadonly = vNode.attr('aria-readonly') || 'false';\n if (vNode.hasAttr('readonly') || ariaReadonly.toLowerCase() === 'true') return false;\n const excludedInputTypes = ['submit', 'reset', 'button', 'hidden'];\n if (nodeName === 'input' && excludedInputTypes.includes(vNode.props.type as string)) return false;\n const ariaDisabled = vNode.attr('aria-disabled') || 'false';\n if (vNode.hasAttr('disabled') || ariaDisabled.toLowerCase() === 'true') return false;\n const role = getExplicitRole(vNode);\n const tabIndex = parseTabindex(vNode.attr('tabindex'));\n if (tabIndex !== null && tabIndex < 0 && vNode.hasAttr('role')) {\n const roleDef = ariaRoles[role as string];\n if (roleDef === undefined || roleDef.type !== 'widget') return false;\n }\n if (\n tabIndex !== null &&\n tabIndex < 0 &&\n vNode.actualNode &&\n !isVisibleOnScreen(vNode) &&\n !isVisibleToScreenReaders(vNode)\n ) {\n return false;\n }\n return true;\n};\n\nconst nestedInteractiveMatch: MatchFn = (_node, vNode) => {\n const role = getRole(vNode);\n if (!role) return false;\n return !!ariaRoles[role].childrenPresentational;\n};\n\nconst dataTableLargeMatch: MatchFn = (node) => {\n if (isDataTable(node as never)) {\n const tableArray = toArray(node as never);\n return (\n tableArray.length >= 3 &&\n tableArray[0].length >= 3 &&\n tableArray[1].length >= 3 &&\n tableArray[2].length >= 3\n );\n }\n return false;\n};\n\nconst dataTableMatch: MatchFn = (node) => isDataTable(node as never);\n\nconst tableOrGridRoleMatch: MatchFn = (_node, vNode) =>\n ['treegrid', 'grid', 'table'].includes(getRole(vNode) as string);\n\nconst noNegativeTabindexMatch: MatchFn = (_node, vNode) => {\n const tabindex = parseTabindex(vNode.attr('tabindex'));\n return tabindex === null || tabindex >= 0;\n};\n\nconst frameTitleHasTextMatch: MatchFn = (node) => {\n const title = (node as unknown as { getAttribute: (a: string) => string | null }).getAttribute('title');\n return !!sanitize(title);\n};\n\nconst hasImplicitChromiumRoleMatch: MatchFn = (_node, vNode) =>\n getImplicitRole(vNode, { chromium: true }) !== null;\n\nconst noExplicitNameRequiredMatch: MatchFn = (_node, vNode) => {\n const role = getExplicitRole(vNode);\n if (!role || ['none', 'presentation'].includes(role)) return true;\n const { accessibleNameRequired } = (ariaRoles[role] || {}) as { accessibleNameRequired?: boolean };\n if (accessibleNameRequired || isFocusable(vNode)) return true;\n return false;\n};\n\nconst labelMatch: MatchFn = (_node, vNode) => {\n if (vNode.props.nodeName !== 'input' || vNode.hasAttr('type') === false) return true;\n const type = (vNode.attr('type') || '').toLowerCase();\n return ['hidden', 'image', 'button', 'submit', 'reset'].includes(type) === false;\n};\n\nconst noNamingMethodMatch: MatchFn = (_node, vNode) => {\n const { namingMethods } = getElementSpec(vNode) as { namingMethods?: string[] };\n if (namingMethods && namingMethods.length !== 0) return false;\n if (getExplicitRole(vNode) === 'combobox' && querySelectorAll(vNode, 'input:not([type=\"hidden\"])').length) {\n return false;\n }\n if (isComboboxPopup(vNode, { popupRoles: ['listbox'] })) return false;\n return true;\n};\n\nconst landmarkUniqueMatch: MatchFn = (_node, vNode) => isLandmark(vNode) && isVisibleToScreenReaders(vNode);\n\nfunction isLandmark(vNode: VNode): boolean {\n const landmarkRoles = getAriaRolesByType('landmark');\n const role = getRole(vNode);\n if (!role) return false;\n const { nodeName } = vNode.props;\n if (nodeName === 'section' || nodeName === 'form') {\n return !!accessibleTextVirtual(vNode);\n }\n return landmarkRoles.indexOf(role) >= 0 || role === 'region';\n}\n\n// ── rule definitions ─────────────────────────────────────────────\n\ninterface RuleDef {\n id: string;\n selector: string;\n matches?: MatchFn;\n excludeHidden: boolean;\n all: string[];\n any: string[];\n none: string[];\n /** axe rules with `reviewOnFail:true` report violations as \"incomplete\". */\n reviewOnFail?: boolean;\n}\n\nconst RULES: RuleDef[] = [\n { id: 'aria-hidden-body', selector: 'body', matches: isInitiator, excludeHidden: false, all: [], any: ['aria-hidden-body'], none: [] },\n { id: 'aria-roles', selector: '[role]', matches: noEmptyRole, excludeHidden: true, all: [], any: [], none: ['invalidrole', 'abstractrole', 'unsupportedrole'] },\n { id: 'aria-deprecated-role', selector: '[role]', matches: noEmptyRole, excludeHidden: true, all: [], any: [], none: ['deprecatedrole'] },\n { id: 'aria-allowed-role', selector: '[role]', matches: ariaAllowedRoleMatch, excludeHidden: false, all: [], any: ['aria-allowed-role'], none: [] },\n { id: 'aria-valid-attr', selector: '*', matches: ariaHasAttr, excludeHidden: true, all: [], any: ['aria-valid-attr'], none: [] },\n { id: 'aria-valid-attr-value', selector: '*', matches: ariaHasAttr, excludeHidden: true, all: ['aria-valid-attr-value', 'aria-errormessage', 'aria-level'], any: [], none: [] },\n { id: 'aria-allowed-attr', selector: '*', matches: ariaHasAttr, excludeHidden: true, all: ['aria-allowed-attr', 'aria-allowed-attr-elm'], any: [], none: ['aria-unsupported-attr'] },\n { id: 'aria-prohibited-attr', selector: '*', matches: ariaHasAttr, excludeHidden: true, all: [], any: [], none: ['aria-prohibited-attr'] },\n { id: 'aria-required-attr', selector: '[role]', excludeHidden: true, all: [], any: ['aria-required-attr'], none: [] },\n { id: 'aria-required-children', selector: '[role]', matches: ariaRequiredChildrenMatch, excludeHidden: true, all: [], any: ['aria-required-children'], none: [] },\n { id: 'aria-required-parent', selector: '[role]', matches: ariaRequiredParentMatch, excludeHidden: true, all: [], any: ['aria-required-parent'], none: [] },\n { id: 'duplicate-id-aria', selector: '[id]', matches: duplicateIdAriaMatch, excludeHidden: false, all: [], any: ['duplicate-id-aria'], none: [], reviewOnFail: true },\n { id: 'autocomplete-valid', selector: '*', matches: autocompleteMatch, excludeHidden: true, all: ['autocomplete-valid'], any: [], none: [] },\n { id: 'nested-interactive', selector: '*', matches: nestedInteractiveMatch, excludeHidden: true, all: [], any: ['no-focusable-content'], none: [] },\n { id: 'td-has-header', selector: 'table', matches: dataTableLargeMatch, excludeHidden: true, all: ['td-has-header'], any: [], none: [] },\n { id: 'th-has-data-cells', selector: 'table', matches: dataTableMatch, excludeHidden: true, all: ['th-has-data-cells'], any: [], none: [] },\n { id: 'td-headers-attr', selector: 'table', matches: tableOrGridRoleMatch, excludeHidden: true, all: ['td-headers-attr'], any: [], none: [] },\n { id: 'scope-attr-valid', selector: 'td[scope], th[scope]', excludeHidden: true, all: ['html5-scope', 'scope-value'], any: [], none: [] },\n { id: 'document-title', selector: 'html:not(html *)', matches: isInitiator, excludeHidden: true, all: [], any: ['doc-has-title'], none: [] },\n { id: 'frame-title', selector: 'frame, iframe', matches: noNegativeTabindexMatch, excludeHidden: true, all: [], any: ['non-empty-title', 'aria-label', 'aria-labelledby', 'presentational-role'], none: [] },\n { id: 'frame-title-unique', selector: 'frame[title], iframe[title]', matches: frameTitleHasTextMatch, excludeHidden: true, all: [], any: [], none: ['unique-frame-title'], reviewOnFail: true },\n { id: 'meta-refresh', selector: 'meta[http-equiv=\"refresh\"][content]', excludeHidden: false, all: [], any: ['meta-refresh'], none: [] },\n { id: 'tabindex', selector: '[tabindex]', excludeHidden: true, all: [], any: ['tabindex'], none: [] },\n { id: 'marquee', selector: 'marquee', excludeHidden: false, all: [], any: [], none: ['is-on-screen'] },\n { id: 'blink', selector: 'blink', excludeHidden: false, all: [], any: [], none: ['is-on-screen'] },\n { id: 'presentation-role-conflict', selector: \"img[alt=''], [role=\\\"none\\\"], [role=\\\"presentation\\\"]\", matches: hasImplicitChromiumRoleMatch, excludeHidden: true, all: [], any: [], none: ['is-element-focusable', 'has-global-aria-attribute'] },\n // ── name/label/landmark rules (replace the hand-rolled cheerio audits) ──\n { id: 'button-name', selector: 'button', matches: noExplicitNameRequiredMatch, excludeHidden: true, all: [], any: ['button-has-visible-text', 'aria-label', 'aria-labelledby', 'non-empty-title', 'implicit-label', 'explicit-label', 'presentational-role'], none: [] },\n { id: 'link-name', selector: 'a[href]', excludeHidden: true, all: [], any: ['has-visible-text', 'aria-label', 'aria-labelledby', 'non-empty-title'], none: ['focusable-no-name'] },\n { id: 'label', selector: 'input, textarea', matches: labelMatch, excludeHidden: true, all: [], any: ['implicit-label', 'explicit-label', 'aria-label', 'aria-labelledby', 'non-empty-title', 'non-empty-placeholder', 'presentational-role'], none: ['hidden-explicit-label'] },\n { id: 'select-name', selector: 'select', excludeHidden: true, all: [], any: ['implicit-label', 'explicit-label', 'aria-label', 'aria-labelledby', 'non-empty-title', 'presentational-role'], none: ['hidden-explicit-label'] },\n { id: 'aria-dialog-name', selector: '[role=\"dialog\"], [role=\"alertdialog\"]', matches: noNamingMethodMatch, excludeHidden: true, all: [], any: ['aria-label', 'aria-labelledby', 'non-empty-title'], none: [] },\n { id: 'landmark-unique', selector: '[role=banner], [role=complementary], [role=contentinfo], [role=main], [role=navigation], [role=region], [role=search], [role=form], form, footer, header, aside, main, nav, section', matches: landmarkUniqueMatch, excludeHidden: true, all: [], any: ['landmark-is-unique'], none: [] },\n];\n\nexport const SUPPORTED_RULE_IDS = RULES.map((r) => r.id);\nconst RULE_BY_ID = new Map(RULES.map((r) => [r.id, r]));\n\n// ── check evaluation ─────────────────────────────────────────────\n\ninterface RawCheckResult {\n result: boolean | undefined;\n data: unknown;\n related: (VNode | AnyNode)[];\n vNode: VNode;\n node: AnyNode;\n}\n\nfunction runCheck(checkId: string, node: AnyNode, vNode: VNode): RawCheckResult {\n const def: CheckDef = checks[checkId];\n const builder = new CheckBuilder();\n let result: boolean | undefined;\n try {\n result = def.evaluate.call(builder, node, def.options ?? {}, vNode);\n } catch {\n result = undefined;\n }\n return { result, data: builder._data, related: builder._related, vNode, node };\n}\n\ntype GroupStatus = 'pass' | 'fail' | 'incomplete';\n\nfunction allStatus(results: (boolean | undefined)[]): GroupStatus {\n if (results.some((r) => r === false)) return 'fail';\n if (results.some((r) => r === undefined)) return 'incomplete';\n return 'pass';\n}\nfunction noneStatus(results: (boolean | undefined)[]): GroupStatus {\n if (results.some((r) => r === true)) return 'fail';\n if (results.some((r) => r === undefined)) return 'incomplete';\n return 'pass';\n}\nfunction anyStatus(results: (boolean | undefined)[]): GroupStatus {\n if (results.length === 0) return 'pass';\n if (results.some((r) => r === true)) return 'pass';\n if (results.some((r) => r === undefined)) return 'incomplete';\n return 'fail';\n}\n\nfunction combine(...statuses: GroupStatus[]): GroupStatus {\n if (statuses.includes('fail')) return 'fail';\n if (statuses.includes('incomplete')) return 'incomplete';\n return 'pass';\n}\n\n// ── selector / target helpers ────────────────────────────────────\n\nfunction getSelector(node: AnyNode): string {\n const el = node as unknown as {\n nodeName: string;\n getAttribute?: (a: string) => string | null;\n id?: string;\n className?: string;\n };\n const tag = el.nodeName.toLowerCase();\n const id = el.id;\n if (id) return `${tag}#${id}`;\n const cls = typeof el.className === 'string' ? el.className.trim().split(/\\s+/).filter(Boolean) : [];\n if (cls.length) return `${tag}.${cls.slice(0, 2).join('.')}`;\n return tag;\n}\n\nexport interface RuleNodeFinding {\n target: string;\n summary: string;\n}\nexport interface RuleResult {\n status: AxeStatus;\n nodes: RuleNodeFinding[];\n}\n\nfunction qsa(doc: Document, selector: string): AnyNode[] {\n try {\n return Array.from(doc.querySelectorAll(selector));\n } catch {\n return [];\n }\n}\n\n/** Run a single rule against a document, returning its status + failing nodes. */\nexport function runRule(rule: RuleDef, doc: Document): RuleResult {\n const candidates = qsa(doc, rule.selector).filter((node) => {\n const vNode = toVNode(node);\n if (rule.matches && !rule.matches(node, vNode)) return false;\n if (rule.excludeHidden && !isVisibleToScreenReaders(vNode)) return false;\n return true;\n });\n\n if (candidates.length === 0) {\n return { status: 'inapplicable', nodes: [] };\n }\n\n // Evaluate every check for every candidate up-front (needed for `after`).\n const checkIds = [...rule.all, ...rule.any, ...rule.none];\n const perNode = candidates.map((node) => {\n const vNode = toVNode(node);\n const byCheck: Record<string, RawCheckResult> = {};\n for (const cid of checkIds) byCheck[cid] = runCheck(cid, node, vNode);\n return { node, vNode, byCheck };\n });\n\n // Apply `after` reducers (operate across all nodes for a given check).\n for (const cid of checkIds) {\n const after = checks[cid].after;\n if (!after) continue;\n const list = perNode.map((p) => ({ data: p.byCheck[cid].data, result: p.byCheck[cid].result }));\n const reduced = after(list);\n // duplicate-id-after FILTERS; unique-frame-title-after rewrites results in\n // place. Map results back by reference, and drop nodes removed by filtering.\n const kept = new Set(reduced);\n let ri = 0;\n for (let i = 0; i < perNode.length; i++) {\n const entry = list[i];\n if (kept.has(entry)) {\n perNode[i].byCheck[cid].result = entry.result;\n } else {\n perNode[i].byCheck[cid]._removed = true;\n }\n }\n void ri;\n }\n\n let sawFail = false;\n let sawIncomplete = false;\n let sawPass = false;\n const failNodes: RuleNodeFinding[] = [];\n\n for (const p of perNode) {\n // A node removed by an `after` filter is dropped entirely.\n const removed = checkIds.some((cid) => (p.byCheck[cid] as { _removed?: boolean })._removed);\n if (removed) continue;\n\n const allRes = rule.all.map((cid) => p.byCheck[cid].result);\n const anyRes = rule.any.map((cid) => p.byCheck[cid].result);\n const noneRes = rule.none.map((cid) => p.byCheck[cid].result);\n const status = combine(allStatus(allRes), anyStatus(anyRes), noneStatus(noneRes));\n\n if (status === 'fail' && rule.reviewOnFail) {\n // axe converts these violations to \"needs review\".\n sawIncomplete = true;\n } else if (status === 'fail') {\n sawFail = true;\n if (failNodes.length < 5) {\n failNodes.push({ target: getSelector(p.node), summary: '' });\n }\n } else if (status === 'incomplete') {\n sawIncomplete = true;\n } else {\n sawPass = true;\n }\n }\n\n if (sawFail) return { status: 'fail', nodes: failNodes };\n if (sawIncomplete) return { status: 'incomplete', nodes: [] };\n if (sawPass) return { status: 'pass', nodes: [] };\n return { status: 'inapplicable', nodes: [] };\n}\n\n/** Run the given rule ids against a document. */\nexport function runRules(doc: Document, ruleIds: string[]): Record<string, RuleResult> {\n setDocument(doc);\n const out: Record<string, RuleResult> = {};\n for (const id of ruleIds) {\n const rule = RULE_BY_ID.get(id);\n if (!rule) continue;\n out[id] = runRule(rule, doc);\n }\n return out;\n}\n\n// Extend RawCheckResult typing for the `_removed` flag set above.\ninterface RawCheckResult {\n _removed?: boolean;\n}\n","import type { FieldStatus, ProductFieldVerification } from './types';\nimport type { PageContext } from './check-context';\n\nconst PRODUCT_TYPES = ['Product', 'IndividualProduct', 'ProductModel'];\n\n/** Flatten @graph wrappers so nested schema objects are inspectable. */\nfunction flatten(blocks: object[]): Record<string, unknown>[] {\n const flat: Record<string, unknown>[] = [];\n for (const block of blocks) {\n const b = block as Record<string, unknown>;\n if (Array.isArray(b['@graph'])) {\n for (const item of b['@graph']) {\n if (item && typeof item === 'object') flat.push(item as Record<string, unknown>);\n }\n } else {\n flat.push(b);\n }\n }\n return flat;\n}\n\nfunction isType(s: Record<string, unknown>, types: string[]): boolean {\n const t = s['@type'];\n if (typeof t === 'string') return types.includes(t);\n if (Array.isArray(t)) return t.some((x) => types.includes(x as string));\n return false;\n}\n\n/** A field is present only if it carries a real value (not '', null, \"null\"). */\nfunction has(v: unknown): boolean {\n if (v === undefined || v === null) return false;\n if (Array.isArray(v)) return v.some(has);\n if (typeof v === 'object') return Object.keys(v).length > 0;\n const s = String(v as string | number | boolean)\n .trim()\n .toLowerCase();\n return s !== '' && s !== 'null' && s !== 'undefined' && s !== 'n/a';\n}\n\nfunction first(v: unknown): Record<string, unknown> | undefined {\n const arr = Array.isArray(v) ? v : [v];\n return arr.find((x) => x && typeof x === 'object') as Record<string, unknown> | undefined;\n}\n\nconst EMPTY: ProductFieldVerification = {\n sku: 'missing',\n gtin: 'missing',\n brand: 'missing',\n category: 'missing',\n availability: 'missing',\n priceCurrency: 'missing',\n stockLevel: 'missing',\n reviewCount: 'missing',\n};\n\n/**\n * Read product fields straight from the scanned product page(s)' structured\n * data. Looks only at pages typed `product` (the user-supplied product page in\n * full-report mode), mirroring how a search engine parses that page.\n */\nexport function extractProductFieldVerification(pages: PageContext[]): ProductFieldVerification {\n const productPages = pages.filter((p) => p.pageType === 'product');\n\n let product: Record<string, unknown> | undefined;\n let sourceUrl: string | undefined;\n for (const page of productPages) {\n const found = flatten(page.structuredData ?? page.jsonLd).find((s) => isType(s, PRODUCT_TYPES));\n if (found) {\n product = found;\n sourceUrl = page.url;\n break;\n }\n }\n\n if (!product) return { ...EMPTY };\n\n const offer = first(product['offers'] ?? product['offer']);\n const rating = first(product['aggregateRating']);\n const st = (b: boolean): FieldStatus => (b ? 'found' : 'missing');\n\n const hasGtin = ['gtin', 'gtin8', 'gtin12', 'gtin13', 'gtin14'].some((k) => has(product![k]));\n const sku =\n has(product['sku']) ||\n has(product['productSKU']) ||\n has(product['productID']) ||\n has(product['mpn']) ||\n hasGtin;\n\n const price = has(offer?.['price']) || has(product['price']);\n const currency = has(offer?.['priceCurrency']) || has(product['priceCurrency']);\n const availability = has(offer?.['availability']) || has(product['availability']);\n const inventory = has(offer?.['inventoryLevel']) || has(product['inventoryLevel']);\n const reviewCount =\n has(rating?.['reviewCount']) || has(product['reviewCount']) || has(rating?.['ratingCount']);\n\n return {\n sku: st(sku),\n gtin: st(hasGtin),\n brand: st(has(product['brand'])),\n category: st(has(product['category'])),\n availability: st(availability),\n // Price and currency are both required for a clean \"found\"; price-only\n // (e.g. a malformed priceCurrency) reads partial rather than missing.\n priceCurrency: price && currency ? 'found' : price || currency ? 'partial' : 'missing',\n // Explicit inventory count = found; an availability enum alone = partial.\n stockLevel: inventory ? 'found' : availability ? 'partial' : 'missing',\n reviewCount: st(reviewCount),\n sourceUrl,\n };\n}\n","import type { ScanReport } from './types';\nimport { SCORE_TIER_LABELS } from './constants';\n\n/**\n * Generates a pragmatic, rule-based summary for a scan report.\n * Provides immediate business context without LLM latency.\n */\nexport function generateScanSummary(report: Partial<ScanReport>): string {\n const {\n domain,\n overallScore = 0,\n scoreTier,\n categories = [],\n recommendations = [],\n readinessVitals = { commerce: 0, content: 0, botAccessibility: 0, technical: 0 },\n } = report;\n\n const tierLabel = scoreTier ? SCORE_TIER_LABELS[scoreTier] : 'N/A';\n const criticalCount = recommendations.filter((r) => r.priority === 'critical').length;\n const highCount = recommendations.filter((r) => r.priority === 'high').length;\n\n const passCount = categories.reduce((sum, cat) => sum + cat.passCount, 0);\n const totalChecks = categories.reduce(\n (sum, cat) => sum + cat.passCount + cat.warnCount + cat.failCount,\n 0,\n );\n\n // Find strongest and weakest categories\n const sortedCategories = [...categories].sort((a, b) => b.score - a.score);\n const strongest = sortedCategories.length > 0 ? sortedCategories[0] : undefined;\n const weakest =\n sortedCategories.length > 1 ? sortedCategories[sortedCategories.length - 1] : undefined;\n\n const v = readinessVitals;\n const summary = [\n `Scan Report for ${domain}: Overall Readiness ${overallScore}% (${tierLabel}).`,\n `Readiness Vitals: Commerce ${v.commerce}%, Content ${v.content}%, AI Bot Accessibility ${v.botAccessibility}%, Technical Readiness ${v.technical}%.`,\n `Audit Statistics: ${passCount} of ${totalChecks} checks passed.`,\n `Key Issues: ${criticalCount} critical, ${highCount} high priority findings.`,\n strongest ? `Top Strength: ${strongest.name} (${strongest.score}%).` : null,\n weakest && strongest && weakest.id !== strongest.id\n ? `Primary Improvement Area: ${weakest.name} (${weakest.score}%).`\n : null,\n ]\n .filter(Boolean)\n .join(' ');\n\n return summary;\n}\n","import type { FetchResult } from './fetcher';\n\nexport interface WafProtection {\n isBlocked: boolean;\n provider?:\n | 'akamai'\n | 'cloudflare'\n | 'datadome'\n | 'perimeterx'\n | 'imperva'\n | 'kasada'\n | 'aws-waf'\n | 'generic-waf'\n | 'connection-drop';\n name: string;\n reason: string;\n statusCode?: number;\n}\n\n/**\n * Analyzes fetch results (homepage, root files, extra pages) to determine\n * if the target website is behind a bot protection wall or WAF that drops\n * or challenges automated AI agents.\n */\nexport function detectWafProtection(\n targetUrl: string,\n homepageResult: FetchResult | null,\n rootFiles: Record<string, FetchResult>,\n scannedPagesCount: number,\n): WafProtection | null {\n const allResults: FetchResult[] = [];\n if (homepageResult) allResults.push(homepageResult);\n for (const res of Object.values(rootFiles)) {\n if (res) allResults.push(res);\n }\n\n // 1. Check HTTP response headers & body across all responses\n for (const res of allResults) {\n const headers = res.headers || {};\n const server = (headers['server'] || '').toLowerCase();\n const body = (res.body || '').toLowerCase();\n const status = res.status;\n\n // Cloudflare Challenge / Turnstile / 403/503\n if (\n headers['cf-mitigated'] === 'challenge' ||\n ((headers['cf-ray'] !== undefined || server.includes('cloudflare')) && (status === 403 || status === 429 || status === 503)) ||\n (server.includes('cloudflare') && (body.includes('just a moment...') || body.includes('checking your browser') || body.includes('cf-challenge') || body.includes('challenges.cloudflare.com')))\n ) {\n return {\n isBlocked: true,\n provider: 'cloudflare',\n name: 'Cloudflare Turnstile / Managed Challenge',\n reason: status === 403 || status === 503 ? `HTTP ${status} Cloudflare challenge page` : 'Cloudflare bot challenge detected',\n statusCode: status,\n };\n }\n\n // DataDome\n if (\n headers['x-datadome'] !== undefined ||\n headers['x-datadome-response'] !== undefined ||\n body.includes('datadome.co') ||\n body.includes('datadome.js') ||\n body.includes('protected by datadome')\n ) {\n return {\n isBlocked: true,\n provider: 'datadome',\n name: 'DataDome Bot Protection',\n reason: 'DataDome anti-bot challenge detected',\n statusCode: status,\n };\n }\n\n // PerimeterX / HUMAN Security\n if (\n headers['x-perimeterx'] !== undefined ||\n Object.keys(headers).some((h) => h.startsWith('x-px-')) ||\n body.includes('client.perimeterx.net') ||\n body.includes('_pxappid') ||\n body.includes('press & hold')\n ) {\n return {\n isBlocked: true,\n provider: 'perimeterx',\n name: 'HUMAN / PerimeterX Bot Defense',\n reason: 'PerimeterX challenge detected',\n statusCode: status,\n };\n }\n\n // Imperva / Incapsula\n if (\n headers['x-iinfo'] !== undefined ||\n (headers['x-cdn'] || '').toLowerCase().includes('incapsula') ||\n body.includes('_incapsula_resource') ||\n body.includes('request unsuccessful. incapsula incident id')\n ) {\n return {\n isBlocked: true,\n provider: 'imperva',\n name: 'Imperva Incapsula WAF',\n reason: 'Imperva anti-bot block detected',\n statusCode: status,\n };\n }\n\n // Kasada\n if (\n Object.keys(headers).some((h) => h.startsWith('x-kpsdk-')) ||\n body.includes('149e9513-01fa-4fb0-a84e-5686259205d3') ||\n body.includes('k-challenge')\n ) {\n return {\n isBlocked: true,\n provider: 'kasada',\n name: 'Kasada Bot Defense',\n reason: 'Kasada challenge detected',\n statusCode: status,\n };\n }\n\n // Akamai Bot Manager\n if (\n server.includes('akamaighost') ||\n headers['x-akamai-transformed'] !== undefined ||\n headers['akamai-grn'] !== undefined ||\n body.includes(\"you don't have permission to access\") ||\n (status === 403 && body.includes('access denied'))\n ) {\n if (status === 403 || scannedPagesCount === 0) {\n return {\n isBlocked: true,\n provider: 'akamai',\n name: 'Akamai Bot Manager',\n reason: status === 403 ? 'HTTP 403 Akamai access denied' : 'Akamai connection challenge / blocking',\n statusCode: status,\n };\n }\n }\n }\n\n // 2. Check if the homepage or initial page completely failed to load (0 pages accessible)\n if (scannedPagesCount === 0 && homepageResult) {\n const errorMsg = (homepageResult.error || '').toLowerCase();\n \n // Check if domain or headers match Akamai\n const headers = homepageResult.headers || {};\n const server = (headers['server'] || '').toLowerCase();\n if (server.includes('akamaighost') || targetUrl.includes('gucci.com')) {\n return {\n isBlocked: true,\n provider: 'akamai',\n name: 'Akamai Bot Manager',\n reason: 'Akamai dropped crawler TCP/HTTP2 connections or timed out',\n statusCode: homepageResult.status || 0,\n };\n }\n\n if (homepageResult.status === 403 || homepageResult.status === 429) {\n return {\n isBlocked: true,\n provider: 'generic-waf',\n name: 'WAF / Access Firewall',\n reason: `Target server rejected crawler with HTTP ${homepageResult.status}`,\n statusCode: homepageResult.status,\n };\n }\n\n if (homepageResult.status === 0 || errorMsg.includes('timeout') || errorMsg.includes('abort') || errorMsg.includes('econnreset')) {\n return {\n isBlocked: true,\n provider: 'connection-drop',\n name: 'Bot Wall / Aggressive Connection Drop',\n reason: 'Connection dropped or timed out repeatedly on crawler requests',\n statusCode: 0,\n };\n }\n }\n\n return null;\n}\n","import type { PageOverride, PageType, ScanReport } from './types';\nimport { getScoreTier, MAX_PAGES_PER_SCAN, READINESS_WEIGHTS } from './constants';\nimport { logger } from './logger';\nimport { createFetcher, splitCredentials } from './fetcher';\nimport {\n parseHtml,\n extractJsonLd,\n extractMicrodata,\n extractRdfa,\n extractMetaTags,\n extractHeadLinks,\n extractInternalLinks,\n extractNavLinks,\n detectPageType,\n} from './parser';\nimport type { CheckContext, PageContext } from './check-context';\nimport { defaultConfig } from './audit-config';\nimport { runAudits } from './audit-runner';\nimport { runA11yForHtml } from './audits/accessibility/runner';\nimport { A11Y_RULES } from './audits/accessibility';\nimport { extractProductFieldVerification } from './product-fields';\nimport { generateScanSummary } from './summary';\nimport { detectWafProtection } from './waf-detector';\n\nimport type { FetchResult } from './fetcher';\n\ntype ProgressCallback = (pct: number, phase: string) => void | Promise<void>;\n\n// Cap how many pages get the jsdom-based a11y pass. Accessibility issues are\n// template-wide, so the first few pages are representative; this bounds the\n// per-scan cost so one heavy site can't dominate the worker. 0 disables the\n// a11y pass entirely (audits degrade to \"not applicable\").\nconst A11Y_MAX_PAGES = Math.max(0, Number(process.env.SCANNER_A11Y_MAX_PAGES ?? 3));\n\n// ── Page Discovery ─────────────────────────────────────────────\n\nfunction discoverPages(\n homepageUrl: string,\n domain: string,\n rootFiles: Record<string, FetchResult>,\n homepage$: ReturnType<typeof parseHtml>,\n exclude: Set<string>,\n maxAdditional: number,\n): string[] {\n const discovered = new Set<string>();\n\n // 1. Sitemap URLs\n const sitemapBody =\n rootFiles['/sitemap.xml']?.status === 200\n ? rootFiles['/sitemap.xml']!.body\n : rootFiles['/sitemap-index.xml']?.status === 200\n ? rootFiles['/sitemap-index.xml']!.body\n : '';\n\n if (sitemapBody) {\n const $sitemap = parseHtml(sitemapBody);\n $sitemap('loc').each((_, el) => {\n const loc = $sitemap(el).text().trim();\n if (loc && loc.includes(domain)) {\n discovered.add(loc);\n }\n });\n }\n\n // 2. llms.txt links\n if (rootFiles['/llms.txt']?.status === 200) {\n const llmsBody = rootFiles['/llms.txt']!.body;\n const linkRegex = /\\[.*?\\]\\((https?:\\/\\/[^\\s)]+)\\)/g;\n let match;\n while ((match = linkRegex.exec(llmsBody)) !== null) {\n if (match[1]!.includes(domain)) {\n discovered.add(match[1]!);\n }\n }\n }\n\n // 3. Navigation links\n const navLinks = extractNavLinks(homepage$);\n for (const href of navLinks) {\n try {\n const resolved = new URL(href, homepageUrl).href;\n if (resolved.includes(domain)) {\n discovered.add(resolved);\n }\n } catch {\n // Skip invalid URLs\n }\n }\n\n // 4. Internal links from homepage\n const internalLinks = extractInternalLinks(homepage$, domain);\n for (const link of internalLinks) {\n discovered.add(link);\n }\n\n // Remove homepage itself\n const normalized = new URL(homepageUrl).href;\n discovered.delete(normalized);\n discovered.delete(normalized.replace(/\\/$/, ''));\n discovered.delete(normalized.endsWith('/') ? normalized : normalized + '/');\n\n // Classify discovered URLs into buckets by likely page type (URL patterns only)\n const buckets: Record<'product' | 'category' | 'content' | 'other', string[]> = {\n product: [],\n category: [],\n content: [],\n other: [],\n };\n\n for (const url of discovered) {\n // Skip URLs the caller already supplies as explicit page overrides.\n if (exclude.has(url.replace(/\\/$/, ''))) continue;\n const path = new URL(url).pathname.toLowerCase();\n if (/\\/(product|products|p|item|dp)(\\/|$)/.test(path)) {\n buckets.product.push(url);\n } else if (/\\/(category|categories|c|collections?|shop|catalog|department)(\\/|$)/.test(path)) {\n buckets.category.push(url);\n } else if (/\\/(blog|posts|articles|news|guides)(\\/|$)/.test(path)) {\n buckets.content.push(url);\n } else {\n buckets.other.push(url);\n }\n }\n\n // Select pages to maximize type diversity (fill 1 per bucket, then remaining)\n const selected: string[] = [];\n const used = new Set<string>();\n\n for (const key of ['product', 'category', 'content'] as const) {\n const first = buckets[key][0];\n if (first && selected.length < maxAdditional) {\n selected.push(first);\n used.add(first);\n }\n }\n\n // Fill remaining slots from all buckets (product → category → content → other)\n const fillOrder: Array<'product' | 'category' | 'content' | 'other'> = [\n 'product',\n 'category',\n 'content',\n 'other',\n ];\n for (const key of fillOrder) {\n for (const url of buckets[key]) {\n if (selected.length >= maxAdditional) break;\n if (!used.has(url)) {\n selected.push(url);\n used.add(url);\n }\n }\n if (selected.length >= maxAdditional) break;\n }\n\n return selected;\n}\n\n// ── Main Scan ──────────────────────────────────────────────────\n\nexport async function runScan(\n url: string,\n onProgress?: ProgressCallback,\n pageOverrides?: PageOverride[] | null,\n signal?: AbortSignal,\n): Promise<ScanReport> {\n const progress = onProgress ?? (() => {});\n const start = performance.now();\n const fetcher = createFetcher();\n\n const baseUrl = new URL(url).origin;\n const domain = new URL(url).hostname;\n // A basic-auth target (`user:pass@host`) is fetched with credentials (the\n // fetcher turns them into an Authorization header), but they must never be\n // stored or displayed. Use a credential-free URL everywhere the report echoes\n // the scanned URL back.\n const displayUrl = splitCredentials(url).url;\n\n // Normalize user-supplied page overrides: resolve, dedupe (trailing-slash\n // insensitive), and drop any that collide with the homepage. Their declared\n // pageType is forced onto the page context so type-gated audits run.\n const homeKey = new URL(url).href.replace(/\\/$/, '');\n const overrideTypeByKey = new Map<string, PageType>();\n const overrideUrls: string[] = [];\n for (const ov of pageOverrides ?? []) {\n let resolved: string;\n try {\n resolved = new URL(ov.url).href;\n } catch {\n continue;\n }\n const key = resolved.replace(/\\/$/, '');\n if (key === homeKey || overrideTypeByKey.has(key)) continue;\n overrideTypeByKey.set(key, ov.pageType);\n overrideUrls.push(resolved);\n }\n\n logger.debug({ url, domain }, '[orchestrator] Starting runScan');\n\n // ── Phase 1: Root-level file checks (parallel) ───────────────\n signal?.throwIfAborted();\n await progress(5, 'Fetching root files');\n\n const rootFilePaths = [\n '/robots.txt',\n '/llms.txt',\n '/llms-full.txt',\n '/agents.md',\n '/sitemap.xml',\n '/sitemap-index.xml',\n '/rss.xml',\n '/feed.xml',\n '/openapi.json',\n '/openapi.yaml',\n '/.well-known/ai-catalog.json',\n '/.well-known/mcp/servers.json',\n '/.well-known/ucp',\n '/.well-known/agents.json',\n '/.well-known/ai-plugin.json',\n '/.well-known/webmcp',\n '/.well-known/security.txt',\n '/navigation.json',\n '/privacy-policy/',\n '/privacy/',\n '/privacy-policy',\n '/privacy',\n '/policies/privacy-policy',\n '/terms/',\n '/terms',\n '/policies/terms-of-service',\n '/about/',\n '/about-us/',\n '/about',\n ];\n\n logger.debug({ count: rootFilePaths.length }, '[orchestrator] Phase 1: Fetching root files');\n\n const rootResults = await Promise.all(\n rootFilePaths.map((path) => fetcher.fetch({ url: `${baseUrl}${path}`, signal })),\n );\n\n const rootFiles: Record<string, FetchResult> = {};\n rootFilePaths.forEach((path, i) => {\n rootFiles[path] = rootResults[i]!;\n });\n\n await progress(25, 'Root files fetched');\n logger.debug('[orchestrator] Phase 1 complete: Root files fetched');\n\n // ── Phase 2: Page-level checks (parallel per page) ───────────\n signal?.throwIfAborted();\n await progress(30, 'Fetching pages');\n logger.debug('[orchestrator] Phase 2: Fetching pages');\n\n // Fetch homepage first\n const homepageResult = await fetcher.fetch({ url, signal });\n const homepage$ =\n homepageResult.status === 200 && homepageResult.body ? parseHtml(homepageResult.body) : null;\n\n // Reserve slots for overrides, then auto-discover the remainder. Override\n // URLs are excluded from discovery so they are not fetched twice.\n const discoverLimit = Math.max(0, MAX_PAGES_PER_SCAN - 1 - overrideUrls.length);\n const discoveredUrls = homepage$\n ? discoverPages(url, domain, rootFiles, homepage$, new Set(overrideTypeByKey.keys()), discoverLimit)\n : [];\n logger.debug(\n { overrides: overrideUrls.length, discovered: discoveredUrls.length },\n '[orchestrator] Page set: overrides + discovered URLs',\n );\n\n // Fetch overrides first (so they take priority), then discovered pages.\n const extraUrls = [...overrideUrls, ...discoveredUrls];\n\n await progress(40, `Analyzing ${1 + extraUrls.length} pages`);\n\n const extraResults = await Promise.all(\n extraUrls.map((pageUrl) => fetcher.fetch({ url: pageUrl, signal })),\n );\n\n // Build page contexts. The homepage keeps its credential-free URL so scanned\n // credentials never surface in the report's page list.\n const allPageResults = [homepageResult, ...extraResults];\n const allPageUrls = [displayUrl, ...extraUrls];\n\n const pages: PageContext[] = allPageResults\n .map((r, i) => ({ result: r, url: allPageUrls[i]!, index: i }))\n .filter((p) => p.result.status === 200 && p.result.body)\n .map((p) => {\n const $ = parseHtml(p.result.body);\n const jsonLd = extractJsonLd($);\n // Union of every structured-data format search engines read. Product\n // audits consume this; classification uses it too so microdata/RDFa\n // product pages are detected, not just JSON-LD ones.\n const structuredData = [...jsonLd, ...extractMicrodata($), ...extractRdfa($)];\n const meta = extractMetaTags($);\n const isFirstPage = p.index === 0;\n // User-supplied overrides keep their declared type; everything else is\n // classified heuristically.\n const forcedType = overrideTypeByKey.get(p.url.replace(/\\/$/, ''));\n return {\n url: p.url,\n pageType: forcedType ?? detectPageType(p.url, $, structuredData, meta, isFirstPage),\n fetchResult: p.result,\n $,\n jsonLd,\n structuredData,\n meta,\n headLinks: extractHeadLinks($),\n };\n });\n\n // Run the a11y rule engine (over jsdom) for the accessibility-tree audits,\n // capped to the first A11Y_MAX_PAGES pages. Concurrency is bounded inside the\n // runner; failures degrade to no a11yResults (audits → na).\n signal?.throwIfAborted();\n await Promise.all(\n pages.slice(0, A11Y_MAX_PAGES).map(async (p) => {\n p.a11yResults = await runA11yForHtml(p.fetchResult.body, p.url, A11Y_RULES);\n }),\n );\n\n await progress(55, 'Page analysis complete');\n logger.debug(\n { pagesAnalyzed: pages.length },\n '[orchestrator] Phase 2 complete: Page analysis complete',\n );\n\n // ── Phase 3: Run all audits ────────────────────────────────────\n signal?.throwIfAborted();\n await progress(60, 'Running audits');\n logger.debug('[orchestrator] Phase 3: Running audits');\n\n const wafProtection = detectWafProtection(url, homepageResult, rootFiles, pages.length);\n\n const ctx: CheckContext = {\n rootFiles,\n pages,\n domain,\n baseUrl,\n fetch: (options) => fetcher.fetch({ ...options, signal }),\n wafProtection: wafProtection ?? undefined,\n };\n\n const {\n checks: allChecks,\n categories,\n overallScore,\n } = await runAudits(ctx, defaultConfig, (completed, total) => {\n const checkProgress = 60 + Math.round((completed / total) * 30);\n void progress(checkProgress, `Running audits (${completed}/${total})`);\n });\n\n logger.debug('[orchestrator] Phase 3 complete: Audits finished');\n\n // ── Phase 4: Assemble report ─────────────────────────────────\n await progress(97, 'Building report');\n logger.debug('[orchestrator] Phase 4: Building final report');\n\n const durationMs = Math.round(performance.now() - start);\n\n const recommendations = allChecks\n .filter((c) => c.status !== 'pass')\n .slice()\n .sort((a: { priority: string }, b: { priority: string }) => {\n const order: Record<string, number> = { critical: 0, high: 1, medium: 2, low: 3 };\n return (order[a.priority] ?? 3) - (order[b.priority] ?? 3);\n });\n\n // Extract Top 10 Fails (already sorted by priority in recommendations)\n const topFails = recommendations.slice(0, 10);\n\n // Extract Top 10 Passes (sorted by weight)\n const weightMap = new Map<string, number>();\n for (const catId in defaultConfig.audits) {\n for (const reg of defaultConfig.audits[catId]!) {\n weightMap.set(reg.meta.id, reg.meta.weight);\n }\n }\n\n const topPasses = allChecks\n .filter((c) => c.status === 'pass')\n .slice()\n .sort(\n (a: { id: string }, b: { id: string }) =>\n (weightMap.get(b.id) ?? 1) - (weightMap.get(a.id) ?? 1),\n )\n .slice(0, 10);\n\n await progress(100, 'Complete');\n\n const readinessVitals = calculateReadinessVitals(allChecks);\n const readinessScore = Math.round(\n readinessVitals.commerce * READINESS_WEIGHTS.commerce +\n readinessVitals.content * READINESS_WEIGHTS.content +\n readinessVitals.botAccessibility * READINESS_WEIGHTS.botAccessibility +\n readinessVitals.technical * READINESS_WEIGHTS.technical,\n );\n\n const report: ScanReport = {\n scanId: '', // Set by the caller\n url: displayUrl,\n domain,\n overallScore,\n scoreTier: getScoreTier(overallScore),\n summary: '', // Set below\n categories,\n topPasses,\n topFails,\n recommendations,\n pagesScanned: pages.map((p) => ({ url: p.url, pageType: p.pageType })),\n scannedAt: new Date().toISOString(),\n durationMs,\n readinessScore,\n readinessVitals,\n wafProtection: wafProtection ?? undefined,\n // Field-level verification is only trustworthy when the user explicitly\n // supplied the product page. Without a product override we don't guess from\n // auto-discovered pages — leave it unset so the report marks it skipped.\n productFields: [...overrideTypeByKey.values()].includes('product')\n ? extractProductFieldVerification(pages)\n : undefined,\n };\n\n report.summary = generateScanSummary(report);\n logger.debug({ durationMs, score: overallScore }, '[orchestrator] runScan complete');\n\n return report;\n}\n\nfunction calculateReadinessVitals(checks: Array<{ id: string; category: string; score: number }>): {\n commerce: number;\n content: number;\n botAccessibility: number;\n technical: number;\n} {\n const getScore = (ids: string[]) => {\n const matching = checks.filter((c) => ids.includes(c.id));\n if (matching.length === 0) return 0;\n return Math.round((matching.reduce((sum, c) => sum + c.score, 0) / matching.length) * 100);\n };\n\n const getCategoryScoreByPrefix = (prefix: string) => {\n const matching = checks.filter((c) => c.id.startsWith(prefix) || c.category === prefix);\n if (matching.length === 0) return 0;\n return Math.round((matching.reduce((sum, c) => sum + c.score, 0) / matching.length) * 100);\n };\n\n return {\n commerce: getScore(['3.8', '3.14', '3.21', '3.22', '3.23']),\n content: getScore([\n '1.1',\n '1.2',\n '1.3',\n '1.4',\n '1.5',\n '1.6',\n '1.7',\n '1.8',\n '1.9',\n '1.10',\n '9.1',\n '9.2',\n '9.3',\n '9.4',\n '9.5',\n '9.6',\n '9.7',\n '9.8',\n '9.9',\n '9.10',\n '9.11',\n '10.6',\n '10.7',\n '10.8',\n '1.23',\n ]),\n botAccessibility: getCategoryScoreByPrefix('crawler-permissions'),\n technical: getCategoryScoreByPrefix('technical-readiness'),\n };\n}\n","import type { CheckResult, CategoryResult } from './types';\nimport { CATEGORY_WEIGHTS, CATEGORY_NAMES, getScoreTier } from './constants';\n\nexport function calculateCategoryScore(checks: CheckResult[]): number {\n // Not-applicable checks are excluded from the average entirely — they\n // represent \"nothing to assess\", so counting them as 0 would unfairly\n // deflate the score for a feature the site was never expected to have.\n const scored = checks.filter((c) => c.status !== 'na');\n if (scored.length === 0) return 0;\n const total = scored.reduce((sum, c) => sum + c.score, 0);\n return Math.round((total / scored.length) * 100);\n}\n\nexport function buildCategoryResult(\n id: string,\n checks: CheckResult[],\n): CategoryResult {\n return {\n id,\n name: CATEGORY_NAMES[id] ?? id,\n weight: CATEGORY_WEIGHTS[id] ?? 0,\n score: calculateCategoryScore(checks),\n checks,\n passCount: checks.filter((c) => c.status === 'pass').length,\n warnCount: checks.filter((c) => c.status === 'warn').length,\n failCount: checks.filter((c) => c.status === 'fail').length,\n };\n}\n\nexport function calculateOverallScore(categories: CategoryResult[]): number {\n return Math.round(\n categories.reduce((sum, cat) => sum + cat.score * cat.weight, 0),\n );\n}\n\nexport { getScoreTier };\n","import type { WafProtection } from './waf-detector';\nexport type { WafProtection };\n\n// ── Page Types ────────────────────────────────────────────────\n\nexport type PageType = 'homepage' | 'category' | 'product' | 'content';\n\nexport const PAGE_TYPE_LABELS: Record<PageType, string> = {\n homepage: 'Homepage',\n category: 'Category Page',\n product: 'Product Details Page',\n content: 'Content Page',\n};\n\n/**\n * A user-supplied page to scan with an explicit type.\n */\nexport interface PageOverride {\n url: string;\n pageType: PageType;\n}\n\n/** Per-field presence in a product page's structured data. */\nexport type FieldStatus = 'found' | 'partial' | 'missing';\n\n/**\n * Field-level verification of a product page, read directly from its structured\n * data (JSON-LD + Microdata + RDFa).\n */\nexport interface ProductFieldVerification {\n sku: FieldStatus;\n gtin: FieldStatus;\n brand: FieldStatus;\n category: FieldStatus;\n availability: FieldStatus;\n priceCurrency: FieldStatus;\n stockLevel: FieldStatus;\n reviewCount: FieldStatus;\n sourceUrl?: string;\n}\n\n// ── Audit Guidance ────────────────────────────────────────────\n\nexport type FixEffort = 'trivial' | 'easy' | 'moderate' | 'complex';\n\nexport interface AuditGuidance {\n /** Customer-facing explanation of business impact when this audit fails */\n impact: string;\n /** Actionable, concise instructions to fix the issue */\n fix: string;\n /** Canonical code snippet showing the correct implementation */\n code?: string;\n /** Estimated effort to implement the fix */\n effort: FixEffort;\n /** Link to external documentation or spec */\n docsUrl?: string;\n /** Tags for filtering/grouping in the report UI */\n tags?: string[];\n}\n\n// ── Audit Meta ────────────────────────────────────────────────\n\nexport type ScoreDisplayMode = 'binary' | 'ternary' | 'informative';\n\nexport interface AuditMeta {\n id: string;\n category: string;\n title: string;\n failureTitle: string;\n description: string;\n scoreDisplayMode: ScoreDisplayMode;\n weight: number;\n applicablePageTypes?: PageType[];\n defaultPriority: CheckPriority;\n guidance?: AuditGuidance;\n}\n\nexport interface AuditResult {\n status: CheckStatus;\n score: number;\n displayValue?: string;\n explanation?: string;\n expected?: string;\n found?: string;\n message?: string;\n details?: {\n expected?: string;\n found?: string;\n code?: string;\n [key: string]: unknown;\n };\n pageUrl?: string;\n priority?: CheckPriority;\n}\n\n// ── Check Results ──────────────────────────────────────────────\n\nexport type CheckStatus = 'pass' | 'warn' | 'fail' | 'na';\n\nexport type CheckPriority = 'critical' | 'high' | 'medium' | 'low';\n\nexport interface CheckRecommendation {\n priority: CheckPriority;\n description: string;\n code?: string;\n docsUrl?: string;\n}\n\nexport interface CheckResult {\n id: string;\n category: string;\n title: string;\n description: string;\n status: CheckStatus;\n score: number;\n scoreDisplayMode: ScoreDisplayMode;\n displayValue?: string;\n explanation?: string;\n pageUrl?: string;\n priority: CheckPriority;\n impact: string;\n fix: string;\n details?: {\n expected?: string;\n found?: string;\n code?: string;\n docsUrl?: string;\n [key: string]: unknown;\n };\n tags?: string[];\n}\n\n// ── Category Results ───────────────────────────────────────────\n\nexport interface CategoryResult {\n id: string;\n name: string;\n weight: number;\n score: number; // 0–100\n checks: CheckResult[];\n passCount: number;\n warnCount: number;\n failCount: number;\n}\n\n// ── Scan Report ────────────────────────────────────────────────\n\nexport type ScoreTier = 'agent-ready' | 'partially-ready' | 'needs-work' | 'not-ready';\n\nexport interface ScanReport {\n scanId: string;\n url: string;\n domain: string;\n overallScore: number;\n scoreTier: ScoreTier;\n summary?: string;\n categories: CategoryResult[];\n topPasses: CheckResult[];\n topFails: CheckResult[];\n categoryScores?: Record<string, number>;\n checkResults?: CheckResult[];\n recommendations: CheckRecommendation[];\n pagesScanned: Array<{ url: string; pageType: PageType }>;\n pagesData?: Array<{ url: string; pageType: PageType }>;\n scannedAt: string;\n createdAt?: string;\n durationMs: number;\n previousScore?: number;\n scoreDelta?: number;\n readinessScore?: number;\n readinessVitals?: ReadinessVitals;\n productFields?: ProductFieldVerification;\n wafProtection?: WafProtection;\n}\n\nexport interface ReadinessVitals {\n commerce: number;\n content: number;\n botAccessibility: number;\n technical: number;\n}\n\n\n","export type PresetName = 'ecommerce' | 'saas' | 'content' | 'quick' | 'full';\n\nexport interface PresetOptions {\n name: PresetName;\n description: string;\n categoryFilter?: string[];\n customWeights?: Record<string, number>;\n maxPages?: number;\n}\n\nexport const PRESETS: Record<PresetName, PresetOptions> = {\n ecommerce: {\n name: 'ecommerce',\n description: 'Optimized for storefronts with heavy focus on Schema.org Product, SKU, GTIN, stock status, and WebMCP actions.',\n customWeights: {\n 'structured-data': 25,\n 'agent-tools': 25,\n 'crawler-permissions': 15,\n 'content-discoverability': 10,\n 'answer-engine': 10,\n 'generative-engine': 5,\n 'meta-tags': 5,\n 'semantic-html': 5,\n },\n },\n saas: {\n name: 'saas',\n description: 'Optimized for software and developer tools focusing on OpenAPI discovery, llms.txt, API permissions, and bot crawling.',\n customWeights: {\n 'agent-tools': 30,\n 'content-discoverability': 20,\n 'crawler-permissions': 20,\n 'technical-readiness': 15,\n 'answer-engine': 15,\n },\n },\n content: {\n name: 'content',\n description: 'Optimized for blogs and publications focusing on llms.txt, RSS feeds, article markup, author credentials, and citations.',\n customWeights: {\n 'content-discoverability': 25,\n 'generative-engine': 25,\n 'answer-engine': 20,\n 'semantic-html': 15,\n 'meta-tags': 15,\n },\n },\n quick: {\n name: 'quick',\n description: 'Fast single-page scan checking only root files (robots.txt, llms.txt, sitemaps) and the homepage.',\n maxPages: 1,\n },\n full: {\n name: 'full',\n description: 'Default comprehensive scan executing all 10 audit categories.',\n },\n};\n\nexport function getPreset(name?: string | null): PresetOptions {\n if (!name) return PRESETS.full;\n const key = name.toLowerCase() as PresetName;\n return PRESETS[key] ?? PRESETS.full;\n}\n","import { existsSync, readFileSync } from 'node:fs';\nimport { resolve } from 'node:path';\nimport type { PresetName } from './presets';\n\nexport interface AgentLighthouseConfig {\n /** Target URL (if not supplied via CLI) */\n url?: string;\n /** Audit preset profile */\n preset?: PresetName;\n /** Categories to execute (default: all) */\n categories?: string[];\n /** Minimum score threshold (0-100) to fail CI */\n minScore?: number;\n /** Per-category minimum score assertions */\n assertCategories?: Record<string, number>;\n /** Output report formats (terminal, html, json, md) */\n output?: Array<'terminal' | 'html' | 'json' | 'md'>;\n /** Output directory for reports */\n outputDir?: string;\n /** Maximum number of pages to discover & scan */\n maxPages?: number;\n}\n\n/** Helper function for type-safe configuration files */\nexport function defineConfig(config: AgentLighthouseConfig): AgentLighthouseConfig {\n return config;\n}\n\nconst DEFAULT_CONFIG_FILES = [\n 'agent-lighthouse.config.json',\n '.agent-lighthouserc.json',\n '.agent-lighthouserc',\n];\n\n/**\n * Loads Agent Lighthouse configuration from a file.\n */\nexport function loadConfigFile(customPath?: string): AgentLighthouseConfig {\n if (customPath) {\n const fullPath = resolve(customPath);\n if (!existsSync(fullPath)) {\n throw new Error(`Config file not found at: ${fullPath}`);\n }\n const content = readFileSync(fullPath, 'utf8');\n return JSON.parse(content) as AgentLighthouseConfig;\n }\n\n for (const filename of DEFAULT_CONFIG_FILES) {\n const fullPath = resolve(process.cwd(), filename);\n if (existsSync(fullPath)) {\n try {\n const content = readFileSync(fullPath, 'utf8');\n return JSON.parse(content) as AgentLighthouseConfig;\n } catch (err) {\n console.warn(`[config] Failed to parse ${filename}:`, err);\n }\n }\n }\n\n return {};\n}\n"],"mappings":"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","names":["base","dns","label","isOk","isOk","isOk","isOk","isOk","cheerio","isOk","cheerio","isOk","getSitemapResult","cheerio","isOk","getSitemapResult","cheerio","isOk","getSitemapResult","isOk","cheerio","isOk","findFeedResult","isOk","isOk","cheerio","isOk","getSitemapResult","allSchemas","matchesType","hasProps","matchesType","extractHeadings","matchesAnyType","allSchemas","hasProps","first","allSchemas","matchesAnyType","allSchemas","matchesType","extractHeadings","matchesAnyType","allSchemas","matchesAnyType","allSchemas","matchesAnyType","first","matchesType","matchesAnyType","allSchemas","hasProps","matchesAnyType","matchesAnyType","first","matchesAnyType","first","tryParseJson","isObject","tryParseJson","isObject","HTTP_METHODS","getOpenApiSpec","getOperations","tryParseJson","isObject","getOpenApiSpec","tryParseJson","isObject","getOpenApiSpec","tryParseJson","isObject","HTTP_METHODS","getOpenApiSpec","getOperations","tryParseJson","isObject","tryParseJson","isObject","tryParseJson","isObject","tryParseJson","isObject","tryParseJson","isObject","tryParseJson","isObject","tryParseJson","isObject","tryParseJson","isObject","tryParseJson","isObject","HTTP_METHODS","getOpenApiSpec","getOperations","tryParseJson","isObject","HTTP_METHODS","getOpenApiSpec","getOperations","tryParseJson","isObject","isObject","tryParseJson","tryParseJson","isObject","asString","tryParseJson","isObject","asString","label","wordCount","matches","wordCount","label","matches","wordCount","DATE_PATTERN","asString","findJsonLdByType","findJsonLdByType","findJsonLdByType","DATE_PATTERN","isArticleContentPage","findJsonLdDate","findStructuredDate","asString","findJsonLdByType","matches","reg","checks","getRootNode","getRootNode","implicitLabel","presentationalRole","unsupported","autocomplete","headers","autocomplete","landmarkRoles","qsa","resolve","first","reg","checks","checks"]}