@pseolint/core 0.1.0 → 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.
- package/dist/ai/adapters/index.d.ts +53 -0
- package/dist/ai/adapters/index.d.ts.map +1 -0
- package/dist/ai/adapters/index.js +158 -0
- package/dist/ai/adapters/index.js.map +1 -0
- package/dist/ai/cache.d.ts +11 -0
- package/dist/ai/cache.d.ts.map +1 -0
- package/dist/ai/cache.js +40 -0
- package/dist/ai/cache.js.map +1 -0
- package/dist/ai/cost.d.ts +3 -0
- package/dist/ai/cost.d.ts.map +1 -0
- package/dist/ai/cost.js +22 -0
- package/dist/ai/cost.js.map +1 -0
- package/dist/ai/feedback-prompt.d.ts +22 -0
- package/dist/ai/feedback-prompt.d.ts.map +1 -0
- package/dist/ai/feedback-prompt.js +39 -0
- package/dist/ai/feedback-prompt.js.map +1 -0
- package/dist/ai/prompt.d.ts +10 -0
- package/dist/ai/prompt.d.ts.map +1 -0
- package/dist/ai/prompt.js +51 -0
- package/dist/ai/prompt.js.map +1 -0
- package/dist/ai/triage.d.ts +22 -0
- package/dist/ai/triage.d.ts.map +1 -0
- package/dist/ai/triage.js +123 -0
- package/dist/ai/triage.js.map +1 -0
- package/dist/ai/types.d.ts +26 -0
- package/dist/ai/types.d.ts.map +1 -0
- package/dist/ai/types.js +2 -0
- package/dist/ai/types.js.map +1 -0
- package/dist/auditor.d.ts.map +1 -1
- package/dist/auditor.js +367 -83
- package/dist/auditor.js.map +1 -1
- package/dist/cache.d.ts +44 -0
- package/dist/cache.d.ts.map +1 -0
- package/dist/cache.js +182 -0
- package/dist/cache.js.map +1 -0
- package/dist/data-source-loader.d.ts +14 -0
- package/dist/data-source-loader.d.ts.map +1 -0
- package/dist/data-source-loader.js +76 -0
- package/dist/data-source-loader.js.map +1 -0
- package/dist/enrich-findings.d.ts.map +1 -1
- package/dist/enrich-findings.js +4 -0
- package/dist/enrich-findings.js.map +1 -1
- package/dist/formatters/console.d.ts.map +1 -1
- package/dist/formatters/console.js +30 -0
- package/dist/formatters/console.js.map +1 -1
- package/dist/formatters/html.d.ts.map +1 -1
- package/dist/formatters/html.js +92 -70
- package/dist/formatters/html.js.map +1 -1
- package/dist/formatters/markdown.d.ts.map +1 -1
- package/dist/formatters/markdown.js +29 -0
- package/dist/formatters/markdown.js.map +1 -1
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -1
- package/dist/rule-references.d.ts.map +1 -1
- package/dist/rule-references.js +3 -0
- package/dist/rule-references.js.map +1 -1
- package/dist/rules/data/data-binding.d.ts +4 -0
- package/dist/rules/data/data-binding.d.ts.map +1 -0
- package/dist/rules/data/data-binding.js +107 -0
- package/dist/rules/data/data-binding.js.map +1 -0
- package/dist/rules/tech/robots-sitemap-presence.d.ts +2 -1
- package/dist/rules/tech/robots-sitemap-presence.d.ts.map +1 -1
- package/dist/rules/tech/robots-sitemap-presence.js +101 -0
- package/dist/rules/tech/robots-sitemap-presence.js.map +1 -1
- package/dist/rules/tech/sitemap-completeness.d.ts.map +1 -1
- package/dist/rules/tech/sitemap-completeness.js +15 -0
- package/dist/rules/tech/sitemap-completeness.js.map +1 -1
- package/dist/state.d.ts +35 -0
- package/dist/state.d.ts.map +1 -0
- package/dist/state.js +64 -0
- package/dist/state.js.map +1 -0
- package/dist/stratified-sample.d.ts +3 -0
- package/dist/stratified-sample.d.ts.map +1 -0
- package/dist/stratified-sample.js +88 -0
- package/dist/stratified-sample.js.map +1 -0
- package/dist/telemetry/aggregator.d.ts +28 -0
- package/dist/telemetry/aggregator.d.ts.map +1 -0
- package/dist/telemetry/aggregator.js +33 -0
- package/dist/telemetry/aggregator.js.map +1 -0
- package/dist/telemetry/index.d.ts +5 -0
- package/dist/telemetry/index.d.ts.map +1 -0
- package/dist/telemetry/index.js +5 -0
- package/dist/telemetry/index.js.map +1 -0
- package/dist/telemetry/reader.d.ts +12 -0
- package/dist/telemetry/reader.d.ts.map +1 -0
- package/dist/telemetry/reader.js +35 -0
- package/dist/telemetry/reader.js.map +1 -0
- package/dist/telemetry/types.d.ts +120 -0
- package/dist/telemetry/types.d.ts.map +1 -0
- package/dist/telemetry/types.js +70 -0
- package/dist/telemetry/types.js.map +1 -0
- package/dist/telemetry/writer.d.ts +12 -0
- package/dist/telemetry/writer.d.ts.map +1 -0
- package/dist/telemetry/writer.js +38 -0
- package/dist/telemetry/writer.js.map +1 -0
- package/dist/types.d.ts +92 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +26 -6
- package/dist/algorithms/entity-mask.test.d.ts +0 -2
- package/dist/algorithms/entity-mask.test.d.ts.map +0 -1
- package/dist/algorithms/entity-mask.test.js +0 -23
- package/dist/algorithms/entity-mask.test.js.map +0 -1
- package/dist/algorithms/simhash.test.d.ts +0 -2
- package/dist/algorithms/simhash.test.d.ts.map +0 -1
- package/dist/algorithms/simhash.test.js +0 -23
- package/dist/algorithms/simhash.test.js.map +0 -1
- package/dist/auditor.test.d.ts +0 -2
- package/dist/auditor.test.d.ts.map +0 -1
- package/dist/auditor.test.js +0 -134
- package/dist/auditor.test.js.map +0 -1
- package/dist/parser.test.d.ts +0 -2
- package/dist/parser.test.d.ts.map +0 -1
- package/dist/parser.test.js +0 -37
- package/dist/parser.test.js.map +0 -1
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
import type { RuleResult } from "../../types.js";
|
|
1
|
+
import type { ParsedPage, RuleResult } from "../../types.js";
|
|
2
2
|
export declare function robotsSitemapPresenceRule(source: string): Promise<RuleResult[]>;
|
|
3
|
+
export declare function robotsComplianceRule(pages: ParsedPage[], sitemapUrls: Set<string>, robotsTxtContent: string): RuleResult[];
|
|
3
4
|
//# sourceMappingURL=robots-sitemap-presence.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"robots-sitemap-presence.d.ts","sourceRoot":"","sources":["../../../src/rules/tech/robots-sitemap-presence.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"robots-sitemap-presence.d.ts","sourceRoot":"","sources":["../../../src/rules/tech/robots-sitemap-presence.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAc7D,wBAAsB,yBAAyB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAqDrF;AA8ED,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,UAAU,EAAE,EACnB,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,EACxB,gBAAgB,EAAE,MAAM,GACvB,UAAU,EAAE,CA+Bd"}
|
|
@@ -58,4 +58,105 @@ export async function robotsSitemapPresenceRule(source) {
|
|
|
58
58
|
}
|
|
59
59
|
return findings;
|
|
60
60
|
}
|
|
61
|
+
/**
|
|
62
|
+
* Parses Disallow directives from the `User-agent: *` block of a robots.txt string.
|
|
63
|
+
* Returns an array of raw pattern strings (e.g. "/secret", "/templates/", "/*.json").
|
|
64
|
+
*/
|
|
65
|
+
function parseDisallowPatterns(robotsTxt) {
|
|
66
|
+
const lines = robotsTxt.split(/\r?\n/);
|
|
67
|
+
const patterns = [];
|
|
68
|
+
let inWildcardBlock = false;
|
|
69
|
+
for (const rawLine of lines) {
|
|
70
|
+
const line = rawLine.trim();
|
|
71
|
+
// Skip comments and blank lines
|
|
72
|
+
if (!line || line.startsWith("#"))
|
|
73
|
+
continue;
|
|
74
|
+
// Detect User-agent directive
|
|
75
|
+
if (/^user-agent\s*:/i.test(line)) {
|
|
76
|
+
const value = line.replace(/^user-agent\s*:\s*/i, "").trim();
|
|
77
|
+
inWildcardBlock = value === "*";
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
if (!inWildcardBlock)
|
|
81
|
+
continue;
|
|
82
|
+
if (/^disallow\s*:/i.test(line)) {
|
|
83
|
+
const value = line.replace(/^disallow\s*:\s*/i, "").trim();
|
|
84
|
+
// Empty Disallow means "allow everything" — skip
|
|
85
|
+
if (value) {
|
|
86
|
+
patterns.push(value);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return patterns;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Returns true if `urlPath` (e.g. "/blog/post") is blocked by a single Disallow pattern.
|
|
94
|
+
*
|
|
95
|
+
* Rules:
|
|
96
|
+
* - Trailing slash: "/foo/" blocks any path starting with "/foo/"
|
|
97
|
+
* - Wildcard `*`: iterative segment matching (no dynamic RegExp — avoids ReDoS)
|
|
98
|
+
* - Exact match otherwise
|
|
99
|
+
*/
|
|
100
|
+
function isBlockedByPattern(urlPath, pattern) {
|
|
101
|
+
if (!pattern)
|
|
102
|
+
return false;
|
|
103
|
+
if (pattern.includes("*")) {
|
|
104
|
+
// Iterative wildcard match: split pattern on `*` and verify each literal
|
|
105
|
+
// segment appears in order within urlPath.
|
|
106
|
+
const parts = pattern.split("*");
|
|
107
|
+
let pos = 0;
|
|
108
|
+
for (let i = 0; i < parts.length; i += 1) {
|
|
109
|
+
const part = parts[i];
|
|
110
|
+
if (i === 0) {
|
|
111
|
+
// First segment must match at the start (robots patterns are prefix-anchored)
|
|
112
|
+
if (!urlPath.startsWith(part))
|
|
113
|
+
return false;
|
|
114
|
+
pos = part.length;
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
const idx = urlPath.indexOf(part, pos);
|
|
118
|
+
if (idx === -1)
|
|
119
|
+
return false;
|
|
120
|
+
pos = idx + part.length;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
return true;
|
|
124
|
+
}
|
|
125
|
+
// Trailing slash: prefix match
|
|
126
|
+
if (pattern.endsWith("/")) {
|
|
127
|
+
return urlPath.startsWith(pattern);
|
|
128
|
+
}
|
|
129
|
+
// Exact match
|
|
130
|
+
return urlPath === pattern;
|
|
131
|
+
}
|
|
132
|
+
export function robotsComplianceRule(pages, sitemapUrls, robotsTxtContent) {
|
|
133
|
+
const disallowPatterns = parseDisallowPatterns(robotsTxtContent);
|
|
134
|
+
if (disallowPatterns.length === 0)
|
|
135
|
+
return [];
|
|
136
|
+
const findings = [];
|
|
137
|
+
for (const page of pages) {
|
|
138
|
+
if (!sitemapUrls.has(page.url))
|
|
139
|
+
continue;
|
|
140
|
+
let parsedPath;
|
|
141
|
+
try {
|
|
142
|
+
parsedPath = new URL(page.url).pathname;
|
|
143
|
+
}
|
|
144
|
+
catch {
|
|
145
|
+
continue;
|
|
146
|
+
}
|
|
147
|
+
for (const pattern of disallowPatterns) {
|
|
148
|
+
if (isBlockedByPattern(parsedPath, pattern)) {
|
|
149
|
+
findings.push({
|
|
150
|
+
ruleId: "tech/robots-compliance",
|
|
151
|
+
severity: "error",
|
|
152
|
+
message: `${page.url} is in the sitemap but blocked by robots.txt (Disallow: ${pattern}).`,
|
|
153
|
+
pageUrl: page.url,
|
|
154
|
+
fix: "Remove the Disallow directive or remove this URL from your sitemap.",
|
|
155
|
+
});
|
|
156
|
+
break; // one finding per page is enough
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return findings;
|
|
161
|
+
}
|
|
61
162
|
//# sourceMappingURL=robots-sitemap-presence.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"robots-sitemap-presence.js","sourceRoot":"","sources":["../../../src/rules/tech/robots-sitemap-presence.ts"],"names":[],"mappings":"AAEA,KAAK,UAAU,aAAa,CAAC,GAAW;IACtC,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;QAClC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,OAAO,IAAI,CAAC;QACd,CAAC;QACD,OAAO,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAAC,MAAc;IAC5D,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QAClC,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC;IAClC,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC;IAChC,MAAM,SAAS,GAAG,GAAG,MAAM,aAAa,CAAC;IACzC,MAAM,UAAU,GAAG,GAAG,MAAM,cAAc,CAAC;IAC3C,MAAM,QAAQ,GAAiB,EAAE,CAAC;IAElC,MAAM,UAAU,GAAG,MAAM,aAAa,CAAC,SAAS,CAAC,CAAC;IAClD,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,8BAA8B;YACtC,QAAQ,EAAE,SAAS;YACnB,OAAO,EAAE,mBAAmB,SAAS,GAAG;YACxC,GAAG,EAAE,+BAA+B,SAAS,4DAA4D;SAC1G,CAAC,CAAC;QACH,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;QAC3C,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,8BAA8B;YACtC,QAAQ,EAAE,MAAM;YAChB,OAAO,EAAE,GAAG,SAAS,wCAAwC;YAC7D,GAAG,EAAE,8BAA8B,SAAS,oBAAoB,UAAU,EAAE;SAC7E,CAAC,CAAC;IACL,CAAC;IAED,MAAM,WAAW,GAAG,MAAM,aAAa,CAAC,UAAU,CAAC,CAAC;IACpD,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,8BAA8B;YACtC,QAAQ,EAAE,SAAS;YACnB,OAAO,EAAE,mBAAmB,UAAU,GAAG;YACzC,GAAG,EAAE,4BAA4B,UAAU,wBAAwB,SAAS,GAAG;SAChF,CAAC,CAAC;QACH,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,MAAM,OAAO,GAAG,WAAW,CAAC,WAAW,EAAE,CAAC;IAC1C,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC;QACvE,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,8BAA8B;YACtC,QAAQ,EAAE,SAAS;YACnB,OAAO,EAAE,GAAG,UAAU,kDAAkD;YACxE,GAAG,EAAE,UAAU,UAAU,6EAA6E;SACvG,CAAC,CAAC;IACL,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
|
1
|
+
{"version":3,"file":"robots-sitemap-presence.js","sourceRoot":"","sources":["../../../src/rules/tech/robots-sitemap-presence.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sitemap-completeness.d.ts","sourceRoot":"","sources":["../../../src/rules/tech/sitemap-completeness.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAE7D,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,UAAU,EAAE,EACnB,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,GACvB,UAAU,EAAE,
|
|
1
|
+
{"version":3,"file":"sitemap-completeness.d.ts","sourceRoot":"","sources":["../../../src/rules/tech/sitemap-completeness.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAE7D,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,UAAU,EAAE,EACnB,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,GACvB,UAAU,EAAE,CA0Dd"}
|
|
@@ -35,6 +35,21 @@ export function sitemapCompletenessRule(pages, sitemapUrls) {
|
|
|
35
35
|
});
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
|
+
for (const page of pages) {
|
|
39
|
+
if (!sitemapUrls.has(page.url))
|
|
40
|
+
continue;
|
|
41
|
+
const hasNoindex = /noindex/i.test(page.robotsMeta) ||
|
|
42
|
+
(page.httpMeta?.xRobotsTag != null && /noindex/i.test(page.httpMeta.xRobotsTag));
|
|
43
|
+
if (hasNoindex) {
|
|
44
|
+
findings.push({
|
|
45
|
+
ruleId: "tech/sitemap-completeness",
|
|
46
|
+
severity: "error",
|
|
47
|
+
message: `${page.url} is in the sitemap but has a noindex directive.`,
|
|
48
|
+
pageUrl: page.url,
|
|
49
|
+
fix: "Remove the noindex directive or remove this URL from your sitemap.",
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
}
|
|
38
53
|
return findings;
|
|
39
54
|
}
|
|
40
55
|
//# sourceMappingURL=sitemap-completeness.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sitemap-completeness.js","sourceRoot":"","sources":["../../../src/rules/tech/sitemap-completeness.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,uBAAuB,CACrC,KAAmB,EACnB,WAAwB;IAExB,IAAI,WAAW,CAAC,IAAI,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAEtC,MAAM,QAAQ,GAAiB,EAAE,CAAC;IAElC,MAAM,kBAAkB,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACxE,IAAI,kBAAkB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAClC,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,2BAA2B;YACnC,QAAQ,EAAE,OAAO;YACjB,OAAO,EAAE,GAAG,kBAAkB,CAAC,MAAM,oCAAoC;YACzE,GAAG,EAAE,sEAAsE;YAC3E,WAAW,EAAE,kBAAkB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE;SACzD,CAAC,CAAC;IACL,CAAC;IAED,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC;YAAE,SAAS;QAE3D,IAAI,IAAI,CAAC,QAAQ,CAAC,UAAU,IAAI,GAAG,EAAE,CAAC;YACpC,QAAQ,CAAC,IAAI,CAAC;gBACZ,MAAM,EAAE,2BAA2B;gBACnC,QAAQ,EAAE,OAAO;gBACjB,OAAO,EAAE,eAAe,IAAI,CAAC,GAAG,iBAAiB,IAAI,CAAC,QAAQ,CAAC,UAAU,GAAG;gBAC5E,OAAO,EAAE,IAAI,CAAC,GAAG;gBACjB,GAAG,EAAE,sEAAsE;aAC5E,CAAC,CAAC;QACL,CAAC;QAED,IAAI,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,KAAK,IAAI,CAAC,GAAG,EAAE,CAAC;YAClF,QAAQ,CAAC,IAAI,CAAC;gBACZ,MAAM,EAAE,2BAA2B;gBACnC,QAAQ,EAAE,SAAS;gBACnB,OAAO,EAAE,eAAe,IAAI,CAAC,GAAG,iBAAiB,IAAI,CAAC,QAAQ,CAAC,QAAQ,GAAG;gBAC1E,OAAO,EAAE,IAAI,CAAC,GAAG;gBACjB,WAAW,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC;gBACrC,GAAG,EAAE,4CAA4C,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE;aAC1E,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
|
1
|
+
{"version":3,"file":"sitemap-completeness.js","sourceRoot":"","sources":["../../../src/rules/tech/sitemap-completeness.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,uBAAuB,CACrC,KAAmB,EACnB,WAAwB;IAExB,IAAI,WAAW,CAAC,IAAI,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAEtC,MAAM,QAAQ,GAAiB,EAAE,CAAC;IAElC,MAAM,kBAAkB,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACxE,IAAI,kBAAkB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAClC,QAAQ,CAAC,IAAI,CAAC;YACZ,MAAM,EAAE,2BAA2B;YACnC,QAAQ,EAAE,OAAO;YACjB,OAAO,EAAE,GAAG,kBAAkB,CAAC,MAAM,oCAAoC;YACzE,GAAG,EAAE,sEAAsE;YAC3E,WAAW,EAAE,kBAAkB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE;SACzD,CAAC,CAAC;IACL,CAAC;IAED,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC;YAAE,SAAS;QAE3D,IAAI,IAAI,CAAC,QAAQ,CAAC,UAAU,IAAI,GAAG,EAAE,CAAC;YACpC,QAAQ,CAAC,IAAI,CAAC;gBACZ,MAAM,EAAE,2BAA2B;gBACnC,QAAQ,EAAE,OAAO;gBACjB,OAAO,EAAE,eAAe,IAAI,CAAC,GAAG,iBAAiB,IAAI,CAAC,QAAQ,CAAC,UAAU,GAAG;gBAC5E,OAAO,EAAE,IAAI,CAAC,GAAG;gBACjB,GAAG,EAAE,sEAAsE;aAC5E,CAAC,CAAC;QACL,CAAC;QAED,IAAI,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,QAAQ,KAAK,IAAI,CAAC,GAAG,EAAE,CAAC;YAClF,QAAQ,CAAC,IAAI,CAAC;gBACZ,MAAM,EAAE,2BAA2B;gBACnC,QAAQ,EAAE,SAAS;gBACnB,OAAO,EAAE,eAAe,IAAI,CAAC,GAAG,iBAAiB,IAAI,CAAC,QAAQ,CAAC,QAAQ,GAAG;gBAC1E,OAAO,EAAE,IAAI,CAAC,GAAG;gBACjB,WAAW,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC;gBACrC,GAAG,EAAE,4CAA4C,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE;aAC1E,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC;YAAE,SAAS;QACzC,MAAM,UAAU,GACd,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC;YAChC,CAAC,IAAI,CAAC,QAAQ,EAAE,UAAU,IAAI,IAAI,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC;QACnF,IAAI,UAAU,EAAE,CAAC;YACf,QAAQ,CAAC,IAAI,CAAC;gBACZ,MAAM,EAAE,2BAA2B;gBACnC,QAAQ,EAAE,OAAO;gBACjB,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,iDAAiD;gBACrE,OAAO,EAAE,IAAI,CAAC,GAAG;gBACjB,GAAG,EAAE,oEAAoE;aAC1E,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
package/dist/state.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export declare const STATE_SCHEMA_VERSION = 1;
|
|
2
|
+
export type RenderMode = "static" | "rendered";
|
|
3
|
+
export interface UrlStateEntry {
|
|
4
|
+
contentHash: string;
|
|
5
|
+
fetchedAt: string;
|
|
6
|
+
status: number;
|
|
7
|
+
findingIds: string[];
|
|
8
|
+
}
|
|
9
|
+
export interface RunState {
|
|
10
|
+
version: number;
|
|
11
|
+
lastRun: string;
|
|
12
|
+
source: string;
|
|
13
|
+
renderMode: RenderMode;
|
|
14
|
+
urls: Record<string, UrlStateEntry>;
|
|
15
|
+
summary: {
|
|
16
|
+
score: number;
|
|
17
|
+
totalFindings: number;
|
|
18
|
+
byCategory: Record<string, number>;
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Normalize HTML so content hashing is stable across irrelevant diffs.
|
|
23
|
+
*
|
|
24
|
+
* Strips: HTML comments, script bodies, style bodies, whitespace runs.
|
|
25
|
+
*
|
|
26
|
+
* Known limitations (use as "likely-unchanged" signal, not proof):
|
|
27
|
+
* - Attribute order changes are NOT normalized (regex parser, not DOM)
|
|
28
|
+
* - Inline event handlers and `data-*` attributes with dynamic values
|
|
29
|
+
* (nonces, CSRF tokens) will produce different hashes
|
|
30
|
+
*/
|
|
31
|
+
export declare function normalizeHtmlForHash(html: string): string;
|
|
32
|
+
export declare function computeContentHash(html: string): string;
|
|
33
|
+
export declare function readState(path: string): Promise<RunState | null>;
|
|
34
|
+
export declare function writeState(path: string, state: RunState): Promise<void>;
|
|
35
|
+
//# sourceMappingURL=state.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state.d.ts","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,oBAAoB,IAAI,CAAC;AAEtC,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,UAAU,CAAC;AAE/C,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,QAAQ;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,UAAU,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IACpC,OAAO,EAAE;QACP,KAAK,EAAE,MAAM,CAAC;QACd,aAAa,EAAE,MAAM,CAAC;QACtB,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KACpC,CAAC;CACH;AAED;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAOzD;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAGvD;AAED,wBAAsB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CA8BtE;AAED,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAK7E"}
|
package/dist/state.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { readFile, writeFile, mkdir, rename } from "node:fs/promises";
|
|
3
|
+
import { dirname } from "node:path";
|
|
4
|
+
export const STATE_SCHEMA_VERSION = 1;
|
|
5
|
+
/**
|
|
6
|
+
* Normalize HTML so content hashing is stable across irrelevant diffs.
|
|
7
|
+
*
|
|
8
|
+
* Strips: HTML comments, script bodies, style bodies, whitespace runs.
|
|
9
|
+
*
|
|
10
|
+
* Known limitations (use as "likely-unchanged" signal, not proof):
|
|
11
|
+
* - Attribute order changes are NOT normalized (regex parser, not DOM)
|
|
12
|
+
* - Inline event handlers and `data-*` attributes with dynamic values
|
|
13
|
+
* (nonces, CSRF tokens) will produce different hashes
|
|
14
|
+
*/
|
|
15
|
+
export function normalizeHtmlForHash(html) {
|
|
16
|
+
return html
|
|
17
|
+
.replace(/<!--[\s\S]*?-->/g, "")
|
|
18
|
+
.replace(/<script[\s\S]*?<\/script>/gi, "<script></script>")
|
|
19
|
+
.replace(/<style[\s\S]*?<\/style>/gi, "<style></style>")
|
|
20
|
+
.replace(/\s+/g, " ")
|
|
21
|
+
.trim();
|
|
22
|
+
}
|
|
23
|
+
export function computeContentHash(html) {
|
|
24
|
+
const norm = normalizeHtmlForHash(html);
|
|
25
|
+
return "sha256:" + createHash("sha256").update(norm).digest("hex");
|
|
26
|
+
}
|
|
27
|
+
export async function readState(path) {
|
|
28
|
+
let raw;
|
|
29
|
+
try {
|
|
30
|
+
raw = await readFile(path, "utf8");
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
let parsed;
|
|
36
|
+
try {
|
|
37
|
+
parsed = JSON.parse(raw);
|
|
38
|
+
}
|
|
39
|
+
catch (e) {
|
|
40
|
+
throw new Error(`state file at ${path} is not valid JSON: ${e.message}`);
|
|
41
|
+
}
|
|
42
|
+
if (!parsed || typeof parsed !== "object") {
|
|
43
|
+
throw new Error(`state file at ${path} is not an object`);
|
|
44
|
+
}
|
|
45
|
+
const state = parsed;
|
|
46
|
+
if (state.version !== STATE_SCHEMA_VERSION) {
|
|
47
|
+
throw new Error(`unsupported state version ${state.version} at ${path}, expected ${STATE_SCHEMA_VERSION}`);
|
|
48
|
+
}
|
|
49
|
+
if (typeof state.lastRun !== "string" ||
|
|
50
|
+
typeof state.source !== "string" ||
|
|
51
|
+
typeof state.renderMode !== "string" ||
|
|
52
|
+
!state.urls || typeof state.urls !== "object" ||
|
|
53
|
+
!state.summary || typeof state.summary !== "object") {
|
|
54
|
+
throw new Error(`state file at ${path} has malformed shape`);
|
|
55
|
+
}
|
|
56
|
+
return state;
|
|
57
|
+
}
|
|
58
|
+
export async function writeState(path, state) {
|
|
59
|
+
await mkdir(dirname(path), { recursive: true });
|
|
60
|
+
const tmp = `${path}.tmp`;
|
|
61
|
+
await writeFile(tmp, JSON.stringify(state, null, 2), "utf8");
|
|
62
|
+
await rename(tmp, path);
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state.js","sourceRoot":"","sources":["../src/state.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AACtE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC;AAwBtC;;;;;;;;;GASG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAAY;IAC/C,OAAO,IAAI;SACR,OAAO,CAAC,kBAAkB,EAAE,EAAE,CAAC;SAC/B,OAAO,CAAC,6BAA6B,EAAE,mBAAmB,CAAC;SAC3D,OAAO,CAAC,2BAA2B,EAAE,iBAAiB,CAAC;SACvD,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;SACpB,IAAI,EAAE,CAAC;AACZ,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,IAAY;IAC7C,MAAM,IAAI,GAAG,oBAAoB,CAAC,IAAI,CAAC,CAAC;IACxC,OAAO,SAAS,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AACrE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,IAAY;IAC1C,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACrC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,MAAe,CAAC;IACpB,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,iBAAiB,IAAI,uBAAwB,CAAW,CAAC,OAAO,EAAE,CAAC,CAAC;IACtF,CAAC;IACD,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC1C,MAAM,IAAI,KAAK,CAAC,iBAAiB,IAAI,mBAAmB,CAAC,CAAC;IAC5D,CAAC;IACD,MAAM,KAAK,GAAG,MAAkB,CAAC;IACjC,IAAI,KAAK,CAAC,OAAO,KAAK,oBAAoB,EAAE,CAAC;QAC3C,MAAM,IAAI,KAAK,CACb,6BAA6B,KAAK,CAAC,OAAO,OAAO,IAAI,cAAc,oBAAoB,EAAE,CAC1F,CAAC;IACJ,CAAC;IACD,IAAI,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ;QACjC,OAAO,KAAK,CAAC,MAAM,KAAK,QAAQ;QAChC,OAAO,KAAK,CAAC,UAAU,KAAK,QAAQ;QACpC,CAAC,KAAK,CAAC,IAAI,IAAI,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ;QAC7C,CAAC,KAAK,CAAC,OAAO,IAAI,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;QACxD,MAAM,IAAI,KAAK,CAAC,iBAAiB,IAAI,sBAAsB,CAAC,CAAC;IAC/D,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAY,EAAE,KAAe;IAC5D,MAAM,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAChD,MAAM,GAAG,GAAG,GAAG,IAAI,MAAM,CAAC;IAC1B,MAAM,SAAS,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;IAC7D,MAAM,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;AAC1B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stratified-sample.d.ts","sourceRoot":"","sources":["../src/stratified-sample.ts"],"names":[],"mappings":"AAeA,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAWpD;AAaD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAwCpE"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
2
|
+
const ULID_RE = /^[0-9A-HJKMNP-TV-Z]{26}$/;
|
|
3
|
+
const DATE_RE = /^\d{4}-\d{2}-\d{2}$/;
|
|
4
|
+
const ALL_DIGITS_RE = /^\d+$/;
|
|
5
|
+
function generalizeSegment(seg) {
|
|
6
|
+
if (!seg)
|
|
7
|
+
return seg;
|
|
8
|
+
if (ALL_DIGITS_RE.test(seg))
|
|
9
|
+
return ":num";
|
|
10
|
+
if (UUID_RE.test(seg) || ULID_RE.test(seg))
|
|
11
|
+
return ":id";
|
|
12
|
+
if (DATE_RE.test(seg))
|
|
13
|
+
return ":date";
|
|
14
|
+
const hyphenCount = (seg.match(/-/g) ?? []).length;
|
|
15
|
+
if (hyphenCount >= 2)
|
|
16
|
+
return ":slug";
|
|
17
|
+
return seg;
|
|
18
|
+
}
|
|
19
|
+
export function inferUrlTemplate(url) {
|
|
20
|
+
let pathname;
|
|
21
|
+
try {
|
|
22
|
+
pathname = new URL(url).pathname;
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
pathname = url;
|
|
26
|
+
}
|
|
27
|
+
if (pathname === "" || pathname === "/")
|
|
28
|
+
return "/";
|
|
29
|
+
const trimmed = pathname.endsWith("/") ? pathname.slice(0, -1) : pathname;
|
|
30
|
+
const segments = trimmed.split("/").slice(1).map(generalizeSegment);
|
|
31
|
+
return "/" + segments.join("/");
|
|
32
|
+
}
|
|
33
|
+
function fisherYates(items, n) {
|
|
34
|
+
const arr = [...items];
|
|
35
|
+
const out = [];
|
|
36
|
+
for (let i = 0; i < n && arr.length > 0; i += 1) {
|
|
37
|
+
const idx = Math.floor(Math.random() * arr.length);
|
|
38
|
+
out.push(arr[idx]);
|
|
39
|
+
arr.splice(idx, 1);
|
|
40
|
+
}
|
|
41
|
+
return out;
|
|
42
|
+
}
|
|
43
|
+
export function stratifiedSample(urls, n) {
|
|
44
|
+
if (n <= 0 || n >= urls.length)
|
|
45
|
+
return [...urls];
|
|
46
|
+
const clusters = new Map();
|
|
47
|
+
for (const u of urls) {
|
|
48
|
+
const t = inferUrlTemplate(u);
|
|
49
|
+
let arr = clusters.get(t);
|
|
50
|
+
if (!arr) {
|
|
51
|
+
arr = [];
|
|
52
|
+
clusters.set(t, arr);
|
|
53
|
+
}
|
|
54
|
+
arr.push(u);
|
|
55
|
+
}
|
|
56
|
+
if (clusters.size <= 1)
|
|
57
|
+
return fisherYates(urls, n);
|
|
58
|
+
const entries = [...clusters.values()];
|
|
59
|
+
const sqrtSizes = entries.map(e => Math.sqrt(e.length));
|
|
60
|
+
const sqrtSum = sqrtSizes.reduce((a, b) => a + b, 0);
|
|
61
|
+
const allocations = sqrtSizes.map(s => Math.floor((s / sqrtSum) * n));
|
|
62
|
+
if (n >= entries.length) {
|
|
63
|
+
for (let i = 0; i < allocations.length; i += 1) {
|
|
64
|
+
if (allocations[i] === 0)
|
|
65
|
+
allocations[i] = 1;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
for (let i = 0; i < allocations.length; i += 1) {
|
|
69
|
+
allocations[i] = Math.min(allocations[i], entries[i].length);
|
|
70
|
+
}
|
|
71
|
+
let total = allocations.reduce((a, b) => a + b, 0);
|
|
72
|
+
while (total < n) {
|
|
73
|
+
const candidates = allocations
|
|
74
|
+
.map((a, i) => ({ idx: i, slack: entries[i].length - a }))
|
|
75
|
+
.filter(x => x.slack > 0);
|
|
76
|
+
if (candidates.length === 0)
|
|
77
|
+
break;
|
|
78
|
+
const chosen = candidates[Math.floor(Math.random() * candidates.length)];
|
|
79
|
+
allocations[chosen.idx] += 1;
|
|
80
|
+
total += 1;
|
|
81
|
+
}
|
|
82
|
+
const result = [];
|
|
83
|
+
for (let i = 0; i < entries.length; i += 1) {
|
|
84
|
+
result.push(...fisherYates(entries[i], allocations[i]));
|
|
85
|
+
}
|
|
86
|
+
return result;
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=stratified-sample.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stratified-sample.js","sourceRoot":"","sources":["../src/stratified-sample.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { TelemetryRecord } from "./types.js";
|
|
2
|
+
export interface TelemetryStats {
|
|
3
|
+
totalAudits: number;
|
|
4
|
+
totalFeedback: number;
|
|
5
|
+
avgDurationMs: number | null;
|
|
6
|
+
avgScore: number | null;
|
|
7
|
+
avgFindings: number | null;
|
|
8
|
+
avgPages: number | null;
|
|
9
|
+
triageUsed: number;
|
|
10
|
+
triageCacheHits: number;
|
|
11
|
+
totalTokenInput: number;
|
|
12
|
+
totalTokenOutput: number;
|
|
13
|
+
totalEstimatedCostUsd: number;
|
|
14
|
+
feedbackBreakdown: {
|
|
15
|
+
helpful: number;
|
|
16
|
+
unhelpful: number;
|
|
17
|
+
skipped: number;
|
|
18
|
+
};
|
|
19
|
+
firstRun: string | null;
|
|
20
|
+
lastRun: string | null;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Pure summary function over a set of telemetry records. Splits audits and
|
|
24
|
+
* feedback, averages the audit-level metrics, and sums triage aggregates over
|
|
25
|
+
* just the audits that included triage.
|
|
26
|
+
*/
|
|
27
|
+
export declare function aggregateTelemetry(records: TelemetryRecord[]): TelemetryStats;
|
|
28
|
+
//# sourceMappingURL=aggregator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aggregator.d.ts","sourceRoot":"","sources":["../../src/telemetry/aggregator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAGV,eAAe,EAChB,MAAM,YAAY,CAAC;AAEpB,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,qBAAqB,EAAE,MAAM,CAAC;IAC9B,iBAAiB,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3E,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,eAAe,EAAE,GACzB,cAAc,CA+ChB"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure summary function over a set of telemetry records. Splits audits and
|
|
3
|
+
* feedback, averages the audit-level metrics, and sums triage aggregates over
|
|
4
|
+
* just the audits that included triage.
|
|
5
|
+
*/
|
|
6
|
+
export function aggregateTelemetry(records) {
|
|
7
|
+
const audits = records.filter((r) => r.type === "audit");
|
|
8
|
+
const feedback = records.filter((r) => r.type === "feedback");
|
|
9
|
+
const n = audits.length;
|
|
10
|
+
const sum = (k) => audits.reduce((s, a) => s + k(a), 0);
|
|
11
|
+
const triageAudits = audits.filter((a) => a.triage);
|
|
12
|
+
return {
|
|
13
|
+
totalAudits: n,
|
|
14
|
+
totalFeedback: feedback.length,
|
|
15
|
+
avgDurationMs: n ? sum((a) => a.durationMs) / n : null,
|
|
16
|
+
avgScore: n ? sum((a) => a.score) / n : null,
|
|
17
|
+
avgFindings: n ? sum((a) => a.findingCount) / n : null,
|
|
18
|
+
avgPages: n ? sum((a) => a.pageCount) / n : null,
|
|
19
|
+
triageUsed: triageAudits.length,
|
|
20
|
+
triageCacheHits: triageAudits.filter((a) => a.triage.cacheHit).length,
|
|
21
|
+
totalTokenInput: triageAudits.reduce((s, a) => s + a.triage.tokenUsage.input, 0),
|
|
22
|
+
totalTokenOutput: triageAudits.reduce((s, a) => s + a.triage.tokenUsage.output, 0),
|
|
23
|
+
totalEstimatedCostUsd: triageAudits.reduce((s, a) => s + (a.triage.estimatedCostUsd ?? 0), 0),
|
|
24
|
+
feedbackBreakdown: {
|
|
25
|
+
helpful: feedback.filter((f) => f.rating === "helpful").length,
|
|
26
|
+
unhelpful: feedback.filter((f) => f.rating === "unhelpful").length,
|
|
27
|
+
skipped: feedback.filter((f) => f.rating === "skipped").length,
|
|
28
|
+
},
|
|
29
|
+
firstRun: audits.reduce((m, a) => (!m || a.timestamp < m ? a.timestamp : m), null),
|
|
30
|
+
lastRun: audits.reduce((m, a) => (!m || a.timestamp > m ? a.timestamp : m), null),
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=aggregator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aggregator.js","sourceRoot":"","sources":["../../src/telemetry/aggregator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/telemetry/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/telemetry/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type TelemetryRecord } from "./types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Read a telemetry JSONL file and return all records that parse successfully
|
|
4
|
+
* against the current schema.
|
|
5
|
+
*
|
|
6
|
+
* - Missing file -> empty array.
|
|
7
|
+
* - Malformed JSON lines -> skipped silently.
|
|
8
|
+
* - Schema-violating lines (e.g. from a future schema version or corruption)
|
|
9
|
+
* -> skipped silently. This keeps the reader forward-compatible.
|
|
10
|
+
*/
|
|
11
|
+
export declare function readTelemetryJsonl(path: string): Promise<TelemetryRecord[]>;
|
|
12
|
+
//# sourceMappingURL=reader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reader.d.ts","sourceRoot":"","sources":["../../src/telemetry/reader.ts"],"names":[],"mappings":"AACA,OAAO,EAAyB,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AAEzE;;;;;;;;GAQG;AACH,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,MAAM,GACX,OAAO,CAAC,eAAe,EAAE,CAAC,CAoB5B"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { telemetryRecordSchema } from "./types.js";
|
|
3
|
+
/**
|
|
4
|
+
* Read a telemetry JSONL file and return all records that parse successfully
|
|
5
|
+
* against the current schema.
|
|
6
|
+
*
|
|
7
|
+
* - Missing file -> empty array.
|
|
8
|
+
* - Malformed JSON lines -> skipped silently.
|
|
9
|
+
* - Schema-violating lines (e.g. from a future schema version or corruption)
|
|
10
|
+
* -> skipped silently. This keeps the reader forward-compatible.
|
|
11
|
+
*/
|
|
12
|
+
export async function readTelemetryJsonl(path) {
|
|
13
|
+
let raw;
|
|
14
|
+
try {
|
|
15
|
+
raw = await readFile(path, "utf8");
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return [];
|
|
19
|
+
}
|
|
20
|
+
const records = [];
|
|
21
|
+
for (const line of raw.split("\n")) {
|
|
22
|
+
const trimmed = line.trim();
|
|
23
|
+
if (!trimmed)
|
|
24
|
+
continue;
|
|
25
|
+
try {
|
|
26
|
+
const json = JSON.parse(trimmed);
|
|
27
|
+
records.push(telemetryRecordSchema.parse(json));
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
// skip malformed / schema-violating lines
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return records;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=reader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reader.js","sourceRoot":"","sources":["../../src/telemetry/reader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,qBAAqB,EAAwB,MAAM,YAAY,CAAC;AAEzE;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,IAAY;IAEZ,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACrC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,OAAO,GAAsB,EAAE,CAAC;IACtC,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACnC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,CAAC,OAAO;YAAE,SAAS;QACvB,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YACjC,OAAO,CAAC,IAAI,CAAC,qBAAqB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;QAClD,CAAC;QAAC,MAAM,CAAC;YACP,0CAA0C;QAC5C,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
|