@qualitykit/engine 0.0.0-stage → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,134 @@
1
+ const DEFAULT_TIMEOUT = 8_000;
2
+ const DEFAULT_MAX_BYTES = 1_000_000;
3
+ export function parseHtmlSignals(html) {
4
+ const title = matchContent(html, /<title[^>]*>([\s\S]*?)<\/title>/i);
5
+ const description = matchAttr(html, /<meta[^>]+name=["']description["'][^>]+content=["']([^"']*)["'][^>]*>/i) ??
6
+ matchAttr(html, /<meta[^>]+content=["']([^"']*)["'][^>]+name=["']description["'][^>]*>/i);
7
+ const canonical = matchAttr(html, /<link[^>]+rel=["']canonical["'][^>]+href=["']([^"']+)["'][^>]*>/i) ??
8
+ matchAttr(html, /<link[^>]+href=["']([^"']+)["'][^>]+rel=["']canonical["'][^>]*>/i);
9
+ const ogTitle = matchAttr(html, /<meta[^>]+property=["']og:title["'][^>]+content=["']([^"']*)["']/i) ??
10
+ matchAttr(html, /<meta[^>]+content=["']([^"']*)["'][^>]+property=["']og:title["']/i);
11
+ const ogDescription = matchAttr(html, /<meta[^>]+property=["']og:description["'][^>]+content=["']([^"']*)["']/i) ??
12
+ matchAttr(html, /<meta[^>]+content=["']([^"']*)["'][^>]+property=["']og:description["']/i);
13
+ const robotsMeta = matchAttr(html, /<meta[^>]+name=["']robots["'][^>]+content=["']([^"']*)["']/i) ??
14
+ matchAttr(html, /<meta[^>]+content=["']([^"']*)["'][^>]+name=["']robots["']/i);
15
+ const h1 = [];
16
+ const headings = [];
17
+ const h1Re = /<h1\b[^>]*>([\s\S]*?)<\/h1>/gi;
18
+ let m;
19
+ while ((m = h1Re.exec(html))) {
20
+ const text = stripTags(m[1]).trim();
21
+ if (text)
22
+ h1.push(text);
23
+ }
24
+ const hRe = /<h([1-3])\b[^>]*>([\s\S]*?)<\/h\1>/gi;
25
+ while ((m = hRe.exec(html))) {
26
+ const text = stripTags(m[2]).trim();
27
+ if (text)
28
+ headings.push(text);
29
+ }
30
+ const jsonLd = [];
31
+ const ldRe = /<script[^>]*type=["']application\/ld\+json["'][^>]*>([\s\S]*?)<\/script>/gi;
32
+ while ((m = ldRe.exec(html))) {
33
+ try {
34
+ jsonLd.push(JSON.parse(m[1]));
35
+ }
36
+ catch {
37
+ // ignore invalid blocks
38
+ }
39
+ }
40
+ return {
41
+ title: title ? stripTags(title).trim() : undefined,
42
+ description: description || undefined,
43
+ canonical: canonical || undefined,
44
+ ogTitle: ogTitle || undefined,
45
+ ogDescription: ogDescription || undefined,
46
+ robotsMeta: robotsMeta || undefined,
47
+ headings,
48
+ h1,
49
+ jsonLd,
50
+ };
51
+ }
52
+ function matchContent(html, re) {
53
+ const m = html.match(re);
54
+ return m?.[1];
55
+ }
56
+ function matchAttr(html, re) {
57
+ const m = html.match(re);
58
+ return m?.[1];
59
+ }
60
+ function stripTags(s) {
61
+ return s.replace(/<[^>]+>/g, " ").replace(/\s+/g, " ");
62
+ }
63
+ export async function fetchRenderedPages(siteUrl, options = {}) {
64
+ const base = siteUrl.replace(/\/$/, "");
65
+ const paths = options.paths?.length ? options.paths : ["/"];
66
+ const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT;
67
+ const maxBytes = options.maxBytes ?? DEFAULT_MAX_BYTES;
68
+ const fetchImpl = options.fetchImpl ?? fetch;
69
+ const results = [];
70
+ for (const path of paths) {
71
+ const url = path.startsWith("http") ? path : `${base}${path === "/" ? "" : path}`;
72
+ const pathName = path.startsWith("http")
73
+ ? safePath(path)
74
+ : path.startsWith("/")
75
+ ? path
76
+ : `/${path}`;
77
+ try {
78
+ const controller = new AbortController();
79
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
80
+ const res = await fetchImpl(url, {
81
+ signal: controller.signal,
82
+ redirect: "follow",
83
+ headers: { "User-Agent": "QualityKitAudit/0.1 (+local-mcp; read-only)" },
84
+ });
85
+ clearTimeout(timer);
86
+ const buf = new Uint8Array(await res.arrayBuffer());
87
+ if (buf.byteLength > maxBytes) {
88
+ results.push({
89
+ url,
90
+ path: pathName,
91
+ ok: false,
92
+ status: res.status,
93
+ error: `Response exceeded ${maxBytes} bytes`,
94
+ headings: [],
95
+ h1: [],
96
+ jsonLd: [],
97
+ });
98
+ continue;
99
+ }
100
+ const html = new TextDecoder("utf-8", { fatal: false }).decode(buf);
101
+ const signals = parseHtmlSignals(html);
102
+ results.push({
103
+ url,
104
+ path: pathName,
105
+ ok: res.ok,
106
+ status: res.status,
107
+ error: res.ok ? undefined : `HTTP ${res.status}`,
108
+ html,
109
+ ...signals,
110
+ });
111
+ }
112
+ catch (error) {
113
+ results.push({
114
+ url,
115
+ path: pathName,
116
+ ok: false,
117
+ error: error instanceof Error ? error.message : "Fetch failed",
118
+ headings: [],
119
+ h1: [],
120
+ jsonLd: [],
121
+ });
122
+ }
123
+ }
124
+ return results;
125
+ }
126
+ function safePath(url) {
127
+ try {
128
+ return new URL(url).pathname || "/";
129
+ }
130
+ catch {
131
+ return "/";
132
+ }
133
+ }
134
+ //# sourceMappingURL=fetch-html.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch-html.js","sourceRoot":"","sources":["../src/fetch-html.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ import type { Severity } from "./site.js";
2
+ export type FindingKind = "defect" | "opportunity";
3
+ export type FixSafety = "auto" | "approval" | "manual";
4
+ export type Confidence = "high" | "medium" | "low";
5
+ export type Impact = "high" | "medium" | "low";
6
+ export type Effort = "low" | "medium" | "high";
7
+ export type FindingCategory = "technical-seo" | "metadata" | "content" | "ai" | "schema" | "links" | "performance" | "conversion";
8
+ export interface Finding {
9
+ id: string;
10
+ kind: FindingKind;
11
+ category: FindingCategory;
12
+ severity: Severity;
13
+ title: string;
14
+ whyItMatters: string;
15
+ evidence: string[];
16
+ suggestedFix: string;
17
+ expectedImpact: Impact;
18
+ confidence: Confidence;
19
+ effort: Effort;
20
+ fixSafety: FixSafety;
21
+ verification: string;
22
+ relatedIds?: string[];
23
+ rootCauseId?: string;
24
+ }
25
+ export interface RouteInventoryItem {
26
+ path: string;
27
+ file: string;
28
+ kind: "page" | "layout" | "route" | "other";
29
+ pattern: "static" | "dynamic" | "handler" | "layout";
30
+ }
31
+ export interface AuditSummary {
32
+ defects: number;
33
+ opportunities: number;
34
+ critical: number;
35
+ high: number;
36
+ medium: number;
37
+ low: number;
38
+ info: number;
39
+ }
40
+ export declare function sortFindings(findings: Finding[]): Finding[];
41
+ export declare function summarizeFindings(findings: Finding[]): AuditSummary;
42
+ export declare function buildRouteInventory(routes: {
43
+ path: string;
44
+ file: string;
45
+ kind: "page" | "layout" | "route" | "other";
46
+ }[]): RouteInventoryItem[];
47
+ //# sourceMappingURL=finding.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding.d.ts","sourceRoot":"","sources":["../src/finding.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAG1C,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,aAAa,CAAC;AAEnD,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,UAAU,GAAG,QAAQ,CAAC;AAEvD,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;AAEnD,MAAM,MAAM,MAAM,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;AAE/C,MAAM,MAAM,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;AAE/C,MAAM,MAAM,eAAe,GACvB,eAAe,GACf,UAAU,GACV,SAAS,GACT,IAAI,GACJ,QAAQ,GACR,OAAO,GACP,aAAa,GACb,YAAY,CAAC;AAEjB,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,WAAW,CAAC;IAClB,QAAQ,EAAE,eAAe,CAAC;IAC1B,QAAQ,EAAE,QAAQ,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,UAAU,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,SAAS,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,GAAG,OAAO,CAAC;IAC5C,OAAO,EAAE,QAAQ,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC;CACtD;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,YAAY,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,OAAO,EAAE,CAgC3D;AAED,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,YAAY,CAUnE;AAED,wBAAgB,mBAAmB,CACjC,MAAM,EAAE;IACN,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,GAAG,OAAO,CAAC;CAC7C,EAAE,GACF,kBAAkB,EAAE,CAatB"}
@@ -0,0 +1,62 @@
1
+ export function sortFindings(findings) {
2
+ const severityRank = {
3
+ critical: 0,
4
+ high: 1,
5
+ medium: 2,
6
+ low: 3,
7
+ info: 4,
8
+ };
9
+ const impactRank = { high: 0, medium: 1, low: 2 };
10
+ const confidenceRank = {
11
+ high: 0,
12
+ medium: 1,
13
+ low: 2,
14
+ };
15
+ const effortRank = { low: 0, medium: 1, high: 2 };
16
+ return [...findings].sort((a, b) => {
17
+ if (a.kind !== b.kind)
18
+ return a.kind === "defect" ? -1 : 1;
19
+ if (severityRank[a.severity] !== severityRank[b.severity]) {
20
+ return severityRank[a.severity] - severityRank[b.severity];
21
+ }
22
+ if (impactRank[a.expectedImpact] !== impactRank[b.expectedImpact]) {
23
+ return impactRank[a.expectedImpact] - impactRank[b.expectedImpact];
24
+ }
25
+ if (confidenceRank[a.confidence] !== confidenceRank[b.confidence]) {
26
+ return confidenceRank[a.confidence] - confidenceRank[b.confidence];
27
+ }
28
+ if (effortRank[a.effort] !== effortRank[b.effort]) {
29
+ return effortRank[a.effort] - effortRank[b.effort];
30
+ }
31
+ return a.id.localeCompare(b.id);
32
+ });
33
+ }
34
+ export function summarizeFindings(findings) {
35
+ return {
36
+ defects: findings.filter((f) => f.kind === "defect").length,
37
+ opportunities: findings.filter((f) => f.kind === "opportunity").length,
38
+ critical: findings.filter((f) => f.severity === "critical").length,
39
+ high: findings.filter((f) => f.severity === "high").length,
40
+ medium: findings.filter((f) => f.severity === "medium").length,
41
+ low: findings.filter((f) => f.severity === "low").length,
42
+ info: findings.filter((f) => f.severity === "info").length,
43
+ };
44
+ }
45
+ export function buildRouteInventory(routes) {
46
+ return routes.map((r) => {
47
+ let pattern = "static";
48
+ if (r.kind === "layout")
49
+ pattern = "layout";
50
+ else if (r.kind === "route")
51
+ pattern = "handler";
52
+ else if (r.path.includes(":"))
53
+ pattern = "dynamic";
54
+ return {
55
+ path: r.path,
56
+ file: r.file,
57
+ kind: r.kind,
58
+ pattern,
59
+ };
60
+ });
61
+ }
62
+ //# sourceMappingURL=finding.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"finding.js","sourceRoot":"","sources":["../src/finding.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ export * from "./finding.js";
2
+ export * from "./site.js";
3
+ export * from "./fetch-html.js";
4
+ export * from "./robots.js";
5
+ export * from "./audit-engine.js";
6
+ export * from "./live-audit.js";
7
+ export * from "./report.js";
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,8 @@
1
+ export * from "./finding.js";
2
+ export * from "./site.js";
3
+ export * from "./fetch-html.js";
4
+ export * from "./robots.js";
5
+ export * from "./audit-engine.js";
6
+ export * from "./live-audit.js";
7
+ export * from "./report.js";
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,WAAW,CAAC;AAC1B,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC;AAC5B,cAAc,mBAAmB,CAAC;AAClC,cAAc,iBAAiB,CAAC;AAChC,cAAc,aAAa,CAAC"}
@@ -0,0 +1,21 @@
1
+ import { type EngineAuditResult } from "./audit-engine.js";
2
+ import { type FetchHtmlOptions, type RenderedPage } from "./fetch-html.js";
3
+ import type { ReportEnvelope } from "./report.js";
4
+ export interface LiveAuditOptions extends FetchHtmlOptions {
5
+ projectName?: string;
6
+ maxSitemapUrls?: number;
7
+ maxExtraPaths?: number;
8
+ }
9
+ export interface LiveAuditResult {
10
+ envelope: ReportEnvelope;
11
+ audit: EngineAuditResult;
12
+ pages: RenderedPage[];
13
+ robotsText?: string;
14
+ sitemapPaths: string[];
15
+ }
16
+ export declare function runLiveAudit(siteUrl: string, options?: LiveAuditOptions): Promise<LiveAuditResult>;
17
+ export declare function diffRegressions(previousFindingIds: string[], current: EngineAuditResult): {
18
+ newDefects: string[];
19
+ stillOpen: string[];
20
+ };
21
+ //# sourceMappingURL=live-audit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"live-audit.d.ts","sourceRoot":"","sources":["../src/live-audit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAC3E,OAAO,EAEL,KAAK,gBAAgB,EACrB,KAAK,YAAY,EAClB,MAAM,iBAAiB,CAAC;AAGzB,OAAO,KAAK,EAAe,cAAc,EAAE,MAAM,aAAa,CAAC;AAM/D,MAAM,WAAW,gBAAiB,SAAQ,gBAAgB;IACxD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,cAAc,CAAC;IACzB,KAAK,EAAE,iBAAiB,CAAC;IACzB,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,wBAAsB,YAAY,CAChC,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,eAAe,CAAC,CA0D1B;AAuJD,wBAAgB,eAAe,CAC7B,kBAAkB,EAAE,MAAM,EAAE,EAC5B,OAAO,EAAE,iBAAiB,GACzB;IAAE,UAAU,EAAE,MAAM,EAAE,CAAC;IAAC,SAAS,EAAE,MAAM,EAAE,CAAA;CAAE,CAS/C"}
@@ -0,0 +1,209 @@
1
+ import { runAuditEngine } from "./audit-engine.js";
2
+ import { fetchRenderedPages, } from "./fetch-html.js";
3
+ import { analyzeRobotsContent, AI_CRAWLERS } from "./robots.js";
4
+ import { wrapReport } from "./report.js";
5
+ const SITEMAP_CAP = 50;
6
+ const EXTRA_PATH_CAP = 8;
7
+ export async function runLiveAudit(siteUrl, options = {}) {
8
+ const base = siteUrl.replace(/\/$/, "");
9
+ const fetchImpl = options.fetchImpl ?? fetch;
10
+ const maxSitemap = options.maxSitemapUrls ?? SITEMAP_CAP;
11
+ const maxExtra = options.maxExtraPaths ?? EXTRA_PATH_CAP;
12
+ const robotsText = await fetchText(`${base}/robots.txt`, fetchImpl);
13
+ const sitemapXml = await fetchText(`${base}/sitemap.xml`, fetchImpl);
14
+ const sitemapPaths = sitemapXml
15
+ ? parseSitemapPaths(sitemapXml, maxSitemap)
16
+ : [];
17
+ const paths = [
18
+ "/",
19
+ ...sitemapPaths.filter((p) => p !== "/").slice(0, maxExtra),
20
+ ];
21
+ const pages = await fetchRenderedPages(base, {
22
+ ...options,
23
+ paths,
24
+ fetchImpl,
25
+ });
26
+ const site = buildLiveSiteModel(base, robotsText, sitemapPaths, pages);
27
+ const audit = runAuditEngine(site, pages);
28
+ const coverage = {
29
+ source: "not_run",
30
+ rendered: pages.some((p) => p.ok) ? "completed" : "not_run",
31
+ live: pages.some((p) => p.ok) ? "completed" : "fail",
32
+ searchData: "not_connected",
33
+ };
34
+ const envelope = wrapReport({
35
+ project: options.projectName ?? new URL(base).hostname,
36
+ mode: "live",
37
+ coverage,
38
+ findings: audit.findings.map((f) => ({
39
+ ruleId: f.id,
40
+ severity: f.severity === "critical" || f.severity === "high" ? "P1" : f.severity === "medium" ? "P2" : "P3",
41
+ status: f.kind === "defect" ? "confirmed" : "needs_verification",
42
+ confidence: f.confidence,
43
+ affectedUrls: extractUrls(f.evidence, base),
44
+ evidence: f.evidence,
45
+ fixable: f.fixSafety === "auto" || f.fixSafety === "approval",
46
+ requiresApproval: f.fixSafety !== "auto",
47
+ title: f.title,
48
+ kind: f.kind,
49
+ })),
50
+ summary: audit.summary,
51
+ });
52
+ return {
53
+ envelope,
54
+ audit,
55
+ pages,
56
+ robotsText: robotsText ?? undefined,
57
+ sitemapPaths,
58
+ };
59
+ }
60
+ function buildLiveSiteModel(siteUrl, robotsText, sitemapPaths, pages) {
61
+ const home = pages.find((p) => p.path === "/" && p.ok);
62
+ const robots = robotsText
63
+ ? analyzeRobotsContent(robotsText)
64
+ : {
65
+ blocksAll: false,
66
+ aiCrawlers: AI_CRAWLERS.map((name) => ({
67
+ name,
68
+ status: "unknown",
69
+ evidence: "robots.txt not fetched",
70
+ })),
71
+ };
72
+ const routes = pages
73
+ .filter((p) => p.ok)
74
+ .map((p) => ({
75
+ path: p.path,
76
+ file: `live:${p.path}`,
77
+ kind: "page",
78
+ title: p.title,
79
+ description: p.description,
80
+ hasMetadata: Boolean(p.title || p.description),
81
+ hasCanonical: Boolean(p.canonical),
82
+ headings: p.headings,
83
+ h1Count: p.h1.length,
84
+ imagesMissingAlt: 0,
85
+ internalLinks: extractInternalHrefs(p.html ?? ""),
86
+ }));
87
+ const jsonTypes = new Set();
88
+ for (const page of pages) {
89
+ for (const block of page.jsonLd) {
90
+ const t = block["@type"];
91
+ if (typeof t === "string")
92
+ jsonTypes.add(t);
93
+ const graph = block["@graph"];
94
+ if (Array.isArray(graph)) {
95
+ for (const node of graph) {
96
+ if (typeof node["@type"] === "string")
97
+ jsonTypes.add(node["@type"]);
98
+ }
99
+ }
100
+ }
101
+ }
102
+ return {
103
+ projectRoot: siteUrl,
104
+ framework: "generic",
105
+ frameworkConfidence: 0.4,
106
+ router: "unknown",
107
+ siteUrl,
108
+ routes,
109
+ metadata: {
110
+ hasMetadataBase: true,
111
+ hasTitleTemplate: false,
112
+ hasRootTitle: Boolean(home?.title),
113
+ hasRootDescription: Boolean(home?.description),
114
+ rootTitle: home?.title,
115
+ rootDescription: home?.description,
116
+ metadataBaseValue: siteUrl,
117
+ },
118
+ robots: {
119
+ present: Boolean(robotsText),
120
+ content: robotsText ?? undefined,
121
+ blocksAll: robots.blocksAll,
122
+ aiCrawlers: robots.aiCrawlers,
123
+ source: robotsText ? "public/robots.txt" : undefined,
124
+ file: robotsText ? "robots.txt" : undefined,
125
+ },
126
+ sitemap: {
127
+ present: sitemapPaths.length > 0,
128
+ routesHint: sitemapPaths,
129
+ source: sitemapPaths.length ? "public/sitemap.xml" : undefined,
130
+ file: sitemapPaths.length ? "sitemap.xml" : undefined,
131
+ },
132
+ redirects: { present: false, count: 0, snippets: [] },
133
+ structuredData: {
134
+ files: pages.filter((p) => p.jsonLd.length).map((p) => `live:${p.path}`),
135
+ types: [...jsonTypes],
136
+ },
137
+ blog: {
138
+ present: sitemapPaths.some((p) => p.startsWith("/blog")),
139
+ routes: sitemapPaths.filter((p) => p.startsWith("/blog")),
140
+ postCount: sitemapPaths.filter((p) => /^\/blog\/.+/.test(p)).length,
141
+ },
142
+ business: {
143
+ name: home?.title,
144
+ description: home?.description,
145
+ audienceHints: [],
146
+ topics: [],
147
+ confidence: home?.title ? 0.6 : 0.3,
148
+ },
149
+ files: [],
150
+ };
151
+ }
152
+ async function fetchText(url, fetchImpl) {
153
+ try {
154
+ const res = await fetchImpl(url, {
155
+ redirect: "follow",
156
+ headers: { "User-Agent": "QualityKitBot/0.3 (+https://qualitykit.dev)" },
157
+ });
158
+ if (!res.ok)
159
+ return null;
160
+ return await res.text();
161
+ }
162
+ catch {
163
+ return null;
164
+ }
165
+ }
166
+ function parseSitemapPaths(xml, cap) {
167
+ const paths = [];
168
+ const re = /<loc>([^<]+)<\/loc>/gi;
169
+ let m;
170
+ while ((m = re.exec(xml)) && paths.length < cap) {
171
+ try {
172
+ const u = new URL(m[1].trim());
173
+ paths.push(u.pathname || "/");
174
+ }
175
+ catch {
176
+ // skip
177
+ }
178
+ }
179
+ return [...new Set(paths)];
180
+ }
181
+ function extractInternalHrefs(html) {
182
+ const links = new Set();
183
+ const re = /href=["'](\/[^"'#?]*)/g;
184
+ let m;
185
+ while ((m = re.exec(html)))
186
+ links.add(m[1]);
187
+ return [...links];
188
+ }
189
+ function extractUrls(evidence, base) {
190
+ const urls = [];
191
+ for (const e of evidence) {
192
+ if (e.startsWith("http"))
193
+ urls.push(e);
194
+ else if (e.startsWith("/"))
195
+ urls.push(`${base.replace(/\/$/, "")}${e}`);
196
+ }
197
+ return urls.length ? urls : ["/"];
198
+ }
199
+ export function diffRegressions(previousFindingIds, current) {
200
+ const prev = new Set(previousFindingIds);
201
+ const currentDefects = current.findings
202
+ .filter((f) => f.kind === "defect")
203
+ .map((f) => f.id);
204
+ return {
205
+ newDefects: currentDefects.filter((id) => !prev.has(id)),
206
+ stillOpen: currentDefects.filter((id) => prev.has(id)),
207
+ };
208
+ }
209
+ //# sourceMappingURL=live-audit.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"live-audit.js","sourceRoot":"","sources":["../src/live-audit.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ export type CoverageStatus = "completed" | "not_run" | "fail" | "not_connected" | "not_applicable";
2
+ export interface CoverageMap {
3
+ source: CoverageStatus;
4
+ rendered: CoverageStatus;
5
+ live: CoverageStatus;
6
+ searchData: CoverageStatus;
7
+ }
8
+ export interface ReportFinding {
9
+ ruleId: string;
10
+ severity: "P1" | "P2" | "P3";
11
+ status: "pass" | "fail" | "confirmed" | "needs_verification" | "not_applicable" | "not_run";
12
+ confidence: "high" | "medium" | "low";
13
+ affectedUrls: string[];
14
+ evidence: string[];
15
+ fixable: boolean;
16
+ requiresApproval: boolean;
17
+ title?: string;
18
+ kind?: "defect" | "opportunity";
19
+ }
20
+ export interface ReportEnvelope {
21
+ schemaVersion: "1.0";
22
+ project: string;
23
+ mode: "full" | "live" | "self_hosted";
24
+ coverage: CoverageMap;
25
+ findings: ReportFinding[];
26
+ summary?: unknown;
27
+ }
28
+ export declare function wrapReport(input: {
29
+ project: string;
30
+ mode: ReportEnvelope["mode"];
31
+ coverage: CoverageMap;
32
+ findings: ReportFinding[];
33
+ summary?: unknown;
34
+ }): ReportEnvelope;
35
+ //# sourceMappingURL=report.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,cAAc,GACtB,WAAW,GACX,SAAS,GACT,MAAM,GACN,eAAe,GACf,gBAAgB,CAAC;AAErB,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,cAAc,CAAC;IACvB,QAAQ,EAAE,cAAc,CAAC;IACzB,IAAI,EAAE,cAAc,CAAC;IACrB,UAAU,EAAE,cAAc,CAAC;CAC5B;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAC7B,MAAM,EACF,MAAM,GACN,MAAM,GACN,WAAW,GACX,oBAAoB,GACpB,gBAAgB,GAChB,SAAS,CAAC;IACd,UAAU,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IACtC,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,QAAQ,GAAG,aAAa,CAAC;CACjC;AAED,MAAM,WAAW,cAAc;IAC7B,aAAa,EAAE,KAAK,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,aAAa,CAAC;IACtC,QAAQ,EAAE,WAAW,CAAC;IACtB,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,wBAAgB,UAAU,CAAC,KAAK,EAAE;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IAC7B,QAAQ,EAAE,WAAW,CAAC;IACtB,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,GAAG,cAAc,CASjB"}
package/dist/report.js ADDED
@@ -0,0 +1,11 @@
1
+ export function wrapReport(input) {
2
+ return {
3
+ schemaVersion: "1.0",
4
+ project: input.project,
5
+ mode: input.mode,
6
+ coverage: input.coverage,
7
+ findings: input.findings,
8
+ summary: input.summary,
9
+ };
10
+ }
11
+ //# sourceMappingURL=report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.js","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"AA0CA,MAAM,UAAU,UAAU,CAAC,KAM1B;IACC,OAAO;QACL,aAAa,EAAE,KAAK;QACpB,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,OAAO,EAAE,KAAK,CAAC,OAAO;KACvB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,10 @@
1
+ export declare const AI_CRAWLERS: readonly ["GPTBot", "Google-Extended", "PerplexityBot", "ClaudeBot", "anthropic-ai", "Bingbot", "Applebot-Extended", "Bytespider"];
2
+ export declare function analyzeRobotsContent(content: string): {
3
+ blocksAll: boolean;
4
+ aiCrawlers: {
5
+ name: string;
6
+ status: "allowed" | "disallowed" | "unknown";
7
+ evidence?: string;
8
+ }[];
9
+ };
10
+ //# sourceMappingURL=robots.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"robots.d.ts","sourceRoot":"","sources":["../src/robots.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,WAAW,oIASd,CAAC;AAEX,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG;IACrD,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE;QACV,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,SAAS,GAAG,YAAY,GAAG,SAAS,CAAC;QAC7C,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,EAAE,CAAC;CACL,CAsEA"}