@tangle-network/browser-agent-driver 0.30.0 → 0.32.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.
Files changed (252) hide show
  1. package/dist/brain/index.d.ts +12 -0
  2. package/dist/brain/index.d.ts.map +1 -1
  3. package/dist/brain/index.js +36 -8
  4. package/dist/brain/index.js.map +1 -1
  5. package/dist/cli-ack-patch.d.ts +39 -0
  6. package/dist/cli-ack-patch.d.ts.map +1 -0
  7. package/dist/cli-ack-patch.js +47 -0
  8. package/dist/cli-ack-patch.js.map +1 -0
  9. package/dist/cli-design-audit.d.ts +12 -0
  10. package/dist/cli-design-audit.d.ts.map +1 -1
  11. package/dist/cli-design-audit.js +78 -0
  12. package/dist/cli-design-audit.js.map +1 -1
  13. package/dist/cli-jobs.d.ts +13 -0
  14. package/dist/cli-jobs.d.ts.map +1 -0
  15. package/dist/cli-jobs.js +253 -0
  16. package/dist/cli-jobs.js.map +1 -0
  17. package/dist/cli-patterns.d.ts +26 -0
  18. package/dist/cli-patterns.d.ts.map +1 -0
  19. package/dist/cli-patterns.js +49 -0
  20. package/dist/cli-patterns.js.map +1 -0
  21. package/dist/cli-reports.d.ts +12 -0
  22. package/dist/cli-reports.d.ts.map +1 -0
  23. package/dist/cli-reports.js +97 -0
  24. package/dist/cli-reports.js.map +1 -0
  25. package/dist/cli.js +29 -1
  26. package/dist/cli.js.map +1 -1
  27. package/dist/design/audit/attribution/aggregate.d.ts +16 -0
  28. package/dist/design/audit/attribution/aggregate.d.ts.map +1 -0
  29. package/dist/design/audit/attribution/aggregate.js +81 -0
  30. package/dist/design/audit/attribution/aggregate.js.map +1 -0
  31. package/dist/design/audit/attribution/store.d.ts +36 -0
  32. package/dist/design/audit/attribution/store.d.ts.map +1 -0
  33. package/dist/design/audit/attribution/store.js +108 -0
  34. package/dist/design/audit/attribution/store.js.map +1 -0
  35. package/dist/design/audit/attribution/types.d.ts +13 -0
  36. package/dist/design/audit/attribution/types.d.ts.map +1 -0
  37. package/dist/design/audit/attribution/types.js +10 -0
  38. package/dist/design/audit/attribution/types.js.map +1 -0
  39. package/dist/design/audit/build-result.d.ts +68 -0
  40. package/dist/design/audit/build-result.d.ts.map +1 -0
  41. package/dist/design/audit/build-result.js +243 -0
  42. package/dist/design/audit/build-result.js.map +1 -0
  43. package/dist/design/audit/classify-ensemble.d.ts +46 -0
  44. package/dist/design/audit/classify-ensemble.d.ts.map +1 -0
  45. package/dist/design/audit/classify-ensemble.js +207 -0
  46. package/dist/design/audit/classify-ensemble.js.map +1 -0
  47. package/dist/design/audit/ethics/check.d.ts +59 -0
  48. package/dist/design/audit/ethics/check.d.ts.map +1 -0
  49. package/dist/design/audit/ethics/check.js +137 -0
  50. package/dist/design/audit/ethics/check.js.map +1 -0
  51. package/dist/design/audit/ethics/loader.d.ts +21 -0
  52. package/dist/design/audit/ethics/loader.d.ts.map +1 -0
  53. package/dist/design/audit/ethics/loader.js +207 -0
  54. package/dist/design/audit/ethics/loader.js.map +1 -0
  55. package/dist/design/audit/ethics/rules/finance.yaml +37 -0
  56. package/dist/design/audit/ethics/rules/kids.yaml +37 -0
  57. package/dist/design/audit/ethics/rules/legal.yaml +35 -0
  58. package/dist/design/audit/ethics/rules/medical.yaml +36 -0
  59. package/dist/design/audit/evaluate.d.ts.map +1 -1
  60. package/dist/design/audit/evaluate.js +4 -1
  61. package/dist/design/audit/evaluate.js.map +1 -1
  62. package/dist/design/audit/first-principles-mode.d.ts +42 -0
  63. package/dist/design/audit/first-principles-mode.d.ts.map +1 -0
  64. package/dist/design/audit/first-principles-mode.js +77 -0
  65. package/dist/design/audit/first-principles-mode.js.map +1 -0
  66. package/dist/design/audit/modality/android.d.ts +14 -0
  67. package/dist/design/audit/modality/android.d.ts.map +1 -0
  68. package/dist/design/audit/modality/android.js +18 -0
  69. package/dist/design/audit/modality/android.js.map +1 -0
  70. package/dist/design/audit/modality/html.d.ts +22 -0
  71. package/dist/design/audit/modality/html.d.ts.map +1 -0
  72. package/dist/design/audit/modality/html.js +51 -0
  73. package/dist/design/audit/modality/html.js.map +1 -0
  74. package/dist/design/audit/modality/index.d.ts +8 -0
  75. package/dist/design/audit/modality/index.d.ts.map +1 -0
  76. package/dist/design/audit/modality/index.js +15 -0
  77. package/dist/design/audit/modality/index.js.map +1 -0
  78. package/dist/design/audit/modality/ios.d.ts +16 -0
  79. package/dist/design/audit/modality/ios.d.ts.map +1 -0
  80. package/dist/design/audit/modality/ios.js +19 -0
  81. package/dist/design/audit/modality/ios.js.map +1 -0
  82. package/dist/design/audit/modality/types.d.ts +9 -0
  83. package/dist/design/audit/modality/types.d.ts.map +1 -0
  84. package/dist/design/audit/modality/types.js +9 -0
  85. package/dist/design/audit/modality/types.js.map +1 -0
  86. package/dist/design/audit/patches/generate.d.ts +45 -0
  87. package/dist/design/audit/patches/generate.d.ts.map +1 -0
  88. package/dist/design/audit/patches/generate.js +161 -0
  89. package/dist/design/audit/patches/generate.js.map +1 -0
  90. package/dist/design/audit/patches/index.d.ts +8 -0
  91. package/dist/design/audit/patches/index.d.ts.map +1 -0
  92. package/dist/design/audit/patches/index.js +5 -0
  93. package/dist/design/audit/patches/index.js.map +1 -0
  94. package/dist/design/audit/patches/parse.d.ts +29 -0
  95. package/dist/design/audit/patches/parse.d.ts.map +1 -0
  96. package/dist/design/audit/patches/parse.js +153 -0
  97. package/dist/design/audit/patches/parse.js.map +1 -0
  98. package/dist/design/audit/patches/render.d.ts +20 -0
  99. package/dist/design/audit/patches/render.d.ts.map +1 -0
  100. package/dist/design/audit/patches/render.js +55 -0
  101. package/dist/design/audit/patches/render.js.map +1 -0
  102. package/dist/design/audit/patches/severity-enforcement.d.ts +23 -0
  103. package/dist/design/audit/patches/severity-enforcement.d.ts.map +1 -0
  104. package/dist/design/audit/patches/severity-enforcement.js +42 -0
  105. package/dist/design/audit/patches/severity-enforcement.js.map +1 -0
  106. package/dist/design/audit/patches/validate.d.ts +40 -0
  107. package/dist/design/audit/patches/validate.d.ts.map +1 -0
  108. package/dist/design/audit/patches/validate.js +60 -0
  109. package/dist/design/audit/patches/validate.js.map +1 -0
  110. package/dist/design/audit/patterns/match.d.ts +24 -0
  111. package/dist/design/audit/patterns/match.d.ts.map +1 -0
  112. package/dist/design/audit/patterns/match.js +48 -0
  113. package/dist/design/audit/patterns/match.js.map +1 -0
  114. package/dist/design/audit/patterns/mine.d.ts +31 -0
  115. package/dist/design/audit/patterns/mine.d.ts.map +1 -0
  116. package/dist/design/audit/patterns/mine.js +35 -0
  117. package/dist/design/audit/patterns/mine.js.map +1 -0
  118. package/dist/design/audit/patterns/store.d.ts +14 -0
  119. package/dist/design/audit/patterns/store.d.ts.map +1 -0
  120. package/dist/design/audit/patterns/store.js +53 -0
  121. package/dist/design/audit/patterns/store.js.map +1 -0
  122. package/dist/design/audit/patterns/types.d.ts +53 -0
  123. package/dist/design/audit/patterns/types.d.ts.map +1 -0
  124. package/dist/design/audit/patterns/types.js +13 -0
  125. package/dist/design/audit/patterns/types.js.map +1 -0
  126. package/dist/design/audit/pipeline.d.ts +12 -0
  127. package/dist/design/audit/pipeline.d.ts.map +1 -1
  128. package/dist/design/audit/pipeline.js +81 -5
  129. package/dist/design/audit/pipeline.js.map +1 -1
  130. package/dist/design/audit/rubric/anchor-loader.d.ts +44 -0
  131. package/dist/design/audit/rubric/anchor-loader.d.ts.map +1 -0
  132. package/dist/design/audit/rubric/anchor-loader.js +210 -0
  133. package/dist/design/audit/rubric/anchor-loader.js.map +1 -0
  134. package/dist/design/audit/rubric/anchors/blog.yaml +33 -0
  135. package/dist/design/audit/rubric/anchors/dashboard.yaml +35 -0
  136. package/dist/design/audit/rubric/anchors/docs.yaml +35 -0
  137. package/dist/design/audit/rubric/anchors/ecommerce.yaml +33 -0
  138. package/dist/design/audit/rubric/anchors/marketing.yaml +34 -0
  139. package/dist/design/audit/rubric/anchors/saas-app.yaml +38 -0
  140. package/dist/design/audit/rubric/anchors/social.yaml +33 -0
  141. package/dist/design/audit/rubric/anchors/tool.yaml +33 -0
  142. package/dist/design/audit/rubric/anchors/utility.yaml +33 -0
  143. package/dist/design/audit/rubric/fragments/audience-clinician.md +42 -0
  144. package/dist/design/audit/rubric/fragments/audience-developer.md +40 -0
  145. package/dist/design/audit/rubric/fragments/audience-kids.md +35 -0
  146. package/dist/design/audit/rubric/fragments/audience-vulnerability-minor-facing.md +37 -0
  147. package/dist/design/audit/rubric/fragments/first-principles.md +65 -0
  148. package/dist/design/audit/rubric/fragments/modality-mobile.md +39 -0
  149. package/dist/design/audit/rubric/fragments/modality-tablet.md +35 -0
  150. package/dist/design/audit/rubric/fragments/regulatory-coppa.md +32 -0
  151. package/dist/design/audit/rubric/fragments/regulatory-gdpr.md +33 -0
  152. package/dist/design/audit/rubric/fragments/regulatory-hipaa.md +36 -0
  153. package/dist/design/audit/rubric/loader.d.ts +26 -6
  154. package/dist/design/audit/rubric/loader.d.ts.map +1 -1
  155. package/dist/design/audit/rubric/loader.js +45 -26
  156. package/dist/design/audit/rubric/loader.js.map +1 -1
  157. package/dist/design/audit/rubric/rollup-weights.d.ts +25 -0
  158. package/dist/design/audit/rubric/rollup-weights.d.ts.map +1 -0
  159. package/dist/design/audit/rubric/rollup-weights.js +51 -0
  160. package/dist/design/audit/rubric/rollup-weights.js.map +1 -0
  161. package/dist/design/audit/score-types.d.ts +431 -0
  162. package/dist/design/audit/score-types.d.ts.map +1 -0
  163. package/dist/design/audit/score-types.js +26 -0
  164. package/dist/design/audit/score-types.js.map +1 -0
  165. package/dist/design/audit/score.d.ts +49 -0
  166. package/dist/design/audit/score.d.ts.map +1 -0
  167. package/dist/design/audit/score.js +211 -0
  168. package/dist/design/audit/score.js.map +1 -0
  169. package/dist/design/audit/types.d.ts +28 -0
  170. package/dist/design/audit/types.d.ts.map +1 -1
  171. package/dist/discover/index.d.ts +16 -0
  172. package/dist/discover/index.d.ts.map +1 -0
  173. package/dist/discover/index.js +25 -0
  174. package/dist/discover/index.js.map +1 -0
  175. package/dist/discover/wayback.d.ts +49 -0
  176. package/dist/discover/wayback.d.ts.map +1 -0
  177. package/dist/discover/wayback.js +123 -0
  178. package/dist/discover/wayback.js.map +1 -0
  179. package/dist/jobs/anti-bot.d.ts +19 -0
  180. package/dist/jobs/anti-bot.d.ts.map +1 -0
  181. package/dist/jobs/anti-bot.js +64 -0
  182. package/dist/jobs/anti-bot.js.map +1 -0
  183. package/dist/jobs/cost-estimate.d.ts +12 -0
  184. package/dist/jobs/cost-estimate.d.ts.map +1 -0
  185. package/dist/jobs/cost-estimate.js +21 -0
  186. package/dist/jobs/cost-estimate.js.map +1 -0
  187. package/dist/jobs/cost-history.d.ts +19 -0
  188. package/dist/jobs/cost-history.d.ts.map +1 -0
  189. package/dist/jobs/cost-history.js +42 -0
  190. package/dist/jobs/cost-history.js.map +1 -0
  191. package/dist/jobs/index.d.ts +31 -0
  192. package/dist/jobs/index.d.ts.map +1 -0
  193. package/dist/jobs/index.js +37 -0
  194. package/dist/jobs/index.js.map +1 -0
  195. package/dist/jobs/orchestrator.d.ts +42 -0
  196. package/dist/jobs/orchestrator.d.ts.map +1 -0
  197. package/dist/jobs/orchestrator.js +282 -0
  198. package/dist/jobs/orchestrator.js.map +1 -0
  199. package/dist/jobs/queue.d.ts +45 -0
  200. package/dist/jobs/queue.d.ts.map +1 -0
  201. package/dist/jobs/queue.js +114 -0
  202. package/dist/jobs/queue.js.map +1 -0
  203. package/dist/jobs/retry.d.ts +36 -0
  204. package/dist/jobs/retry.d.ts.map +1 -0
  205. package/dist/jobs/retry.js +77 -0
  206. package/dist/jobs/retry.js.map +1 -0
  207. package/dist/jobs/store.d.ts +31 -0
  208. package/dist/jobs/store.d.ts.map +1 -0
  209. package/dist/jobs/store.js +92 -0
  210. package/dist/jobs/store.js.map +1 -0
  211. package/dist/jobs/types.d.ts +106 -0
  212. package/dist/jobs/types.d.ts.map +1 -0
  213. package/dist/jobs/types.js +13 -0
  214. package/dist/jobs/types.js.map +1 -0
  215. package/dist/reports/aggregate.d.ts +38 -0
  216. package/dist/reports/aggregate.d.ts.map +1 -0
  217. package/dist/reports/aggregate.js +145 -0
  218. package/dist/reports/aggregate.js.map +1 -0
  219. package/dist/reports/index.d.ts +21 -0
  220. package/dist/reports/index.d.ts.map +1 -0
  221. package/dist/reports/index.js +15 -0
  222. package/dist/reports/index.js.map +1 -0
  223. package/dist/reports/narrate.d.ts +19 -0
  224. package/dist/reports/narrate.d.ts.map +1 -0
  225. package/dist/reports/narrate.js +40 -0
  226. package/dist/reports/narrate.js.map +1 -0
  227. package/dist/reports/templates.d.ts +43 -0
  228. package/dist/reports/templates.d.ts.map +1 -0
  229. package/dist/reports/templates.js +200 -0
  230. package/dist/reports/templates.js.map +1 -0
  231. package/dist/reports/tokens.d.ts +69 -0
  232. package/dist/reports/tokens.d.ts.map +1 -0
  233. package/dist/reports/tokens.js +74 -0
  234. package/dist/reports/tokens.js.map +1 -0
  235. package/dist/reports/tools.d.ts +76 -0
  236. package/dist/reports/tools.d.ts.map +1 -0
  237. package/dist/reports/tools.js +205 -0
  238. package/dist/reports/tools.js.map +1 -0
  239. package/dist/reports/types.d.ts +51 -0
  240. package/dist/reports/types.d.ts.map +1 -0
  241. package/dist/reports/types.js +9 -0
  242. package/dist/reports/types.js.map +1 -0
  243. package/dist/run-state.d.ts +36 -1
  244. package/dist/run-state.d.ts.map +1 -1
  245. package/dist/run-state.js +36 -1
  246. package/dist/run-state.js.map +1 -1
  247. package/dist/runner/runner.d.ts.map +1 -1
  248. package/dist/runner/runner.js +73 -3
  249. package/dist/runner/runner.js.map +1 -1
  250. package/dist/types.d.ts +7 -0
  251. package/dist/types.d.ts.map +1 -1
  252. package/package.json +5 -1
@@ -0,0 +1,145 @@
1
+ /**
2
+ * Deterministic aggregation over a job's per-target audit results.
3
+ *
4
+ * Every number that shows up in a report flows through here — never through
5
+ * an LLM. The narration layer can describe / contextualize / dramatize, but
6
+ * counts, scores, deltas, and rankings are all computed here. Same pattern
7
+ * we use for the audit patches contract: agent narrates, code computes.
8
+ */
9
+ import * as fs from 'node:fs';
10
+ /**
11
+ * Read each ok result's `report.json` from disk and project to AggregateRow.
12
+ * Skipped/failed entries become rows with `rollupScore: NaN` so callers can
13
+ * filter them — keeping them in the list preserves index alignment with
14
+ * `job.results` for tools that want to drill in.
15
+ */
16
+ export function aggregateJob(job) {
17
+ const out = [];
18
+ for (const r of job.results) {
19
+ out.push(toRow(r));
20
+ }
21
+ return out;
22
+ }
23
+ function toRow(r) {
24
+ const base = {
25
+ url: r.url,
26
+ snapshotUrl: r.snapshotUrl,
27
+ capturedAt: r.capturedAt,
28
+ runId: r.runId ?? '',
29
+ rollupScore: typeof r.rollupScore === 'number' ? r.rollupScore : NaN,
30
+ dimensions: {},
31
+ ethicsViolations: 0,
32
+ resultPath: r.resultPath,
33
+ pageType: r.pageType,
34
+ };
35
+ if (r.status !== 'ok' || !r.resultPath || !fs.existsSync(r.resultPath)) {
36
+ return base;
37
+ }
38
+ try {
39
+ const json = JSON.parse(fs.readFileSync(r.resultPath, 'utf-8'));
40
+ const page = json.pages?.[0];
41
+ if (!page)
42
+ return base;
43
+ const result = page.auditResult;
44
+ const cls = result?.classification ?? page.classification ?? {};
45
+ base.pageType = base.pageType ?? cls.type;
46
+ base.domain = cls.domain;
47
+ if (result?.rollup?.score !== undefined)
48
+ base.rollupScore = result.rollup.score;
49
+ else if (page.rollup?.score !== undefined)
50
+ base.rollupScore = page.rollup.score;
51
+ else if (typeof page.score === 'number')
52
+ base.rollupScore = page.score;
53
+ if (result?.scores) {
54
+ for (const [dim, ds] of Object.entries(result.scores)) {
55
+ if (ds && typeof ds.score === 'number')
56
+ base.dimensions[dim] = ds.score;
57
+ }
58
+ }
59
+ base.ethicsViolations = Array.isArray(page.ethicsViolations) ? page.ethicsViolations.length : 0;
60
+ }
61
+ catch {
62
+ // Corrupt or partial report.json — leave as-is. Don't pretend we have data we don't.
63
+ }
64
+ return base;
65
+ }
66
+ export function leaderboard(rows, opts = {}) {
67
+ const dir = opts.direction ?? 'desc';
68
+ const filtered = rows
69
+ .filter(r => Number.isFinite(r.rollupScore))
70
+ .filter(r => !opts.byType || r.pageType === opts.byType);
71
+ filtered.sort((a, b) => (dir === 'desc' ? b.rollupScore - a.rollupScore : a.rollupScore - b.rollupScore));
72
+ if (opts.topN && opts.topN > 0)
73
+ return filtered.slice(0, opts.topN);
74
+ return filtered;
75
+ }
76
+ /** Longitudinal view: all snapshots for one URL, sorted by capture time. */
77
+ export function longitudinalFor(rows, url) {
78
+ return rows
79
+ .filter(r => r.url === url && r.capturedAt && Number.isFinite(r.rollupScore))
80
+ .map(r => ({
81
+ url: r.url,
82
+ capturedAt: r.capturedAt,
83
+ rollupScore: r.rollupScore,
84
+ pageType: r.pageType,
85
+ }))
86
+ .sort((a, b) => a.capturedAt.localeCompare(b.capturedAt));
87
+ }
88
+ export function compareRuns(a, b) {
89
+ const dims = new Set([
90
+ ...Object.keys(a.dimensions),
91
+ ...Object.keys(b.dimensions),
92
+ ]);
93
+ const perDimension = [];
94
+ for (const dim of dims) {
95
+ const ax = a.dimensions[dim];
96
+ const bx = b.dimensions[dim];
97
+ if (typeof ax !== 'number' || typeof bx !== 'number')
98
+ continue;
99
+ perDimension.push({ dim, beforeScore: bx, afterScore: ax, delta: round2(ax - bx) });
100
+ }
101
+ return {
102
+ a,
103
+ b,
104
+ rollupDelta: round2(a.rollupScore - b.rollupScore),
105
+ perDimension,
106
+ };
107
+ }
108
+ export function tierBuckets(rows, boundaries) {
109
+ const ranked = leaderboard(rows);
110
+ const buckets = [];
111
+ const sorted = [...new Set(boundaries)].sort((a, b) => a - b);
112
+ let prev = 0;
113
+ for (const upper of sorted) {
114
+ const slice = ranked.slice(prev, upper);
115
+ if (slice.length === 0) {
116
+ prev = upper;
117
+ continue;
118
+ }
119
+ const label = prev === 0 ? `top ${upper}` : `${prev + 1}–${upper}`;
120
+ buckets.push({ label, rows: slice, ...stats(slice) });
121
+ prev = upper;
122
+ }
123
+ if (prev < ranked.length) {
124
+ const slice = ranked.slice(prev);
125
+ buckets.push({ label: `${prev + 1}+`, rows: slice, ...stats(slice) });
126
+ }
127
+ return buckets;
128
+ }
129
+ function stats(rows) {
130
+ if (rows.length === 0)
131
+ return { meanScore: NaN, medianScore: NaN };
132
+ const scores = rows.map(r => r.rollupScore).filter(Number.isFinite);
133
+ const sum = scores.reduce((a, b) => a + b, 0);
134
+ const sorted = [...scores].sort((a, b) => a - b);
135
+ const mid = Math.floor(sorted.length / 2);
136
+ const median = sorted.length % 2 === 0 ? (sorted[mid - 1] + sorted[mid]) / 2 : sorted[mid];
137
+ return {
138
+ meanScore: round2(sum / scores.length),
139
+ medianScore: round2(median),
140
+ };
141
+ }
142
+ function round2(n) {
143
+ return Math.round(n * 100) / 100;
144
+ }
145
+ //# sourceMappingURL=aggregate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aggregate.js","sourceRoot":"","sources":["../../src/reports/aggregate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Reports — turn a job's audit results into shareable artifacts.
3
+ *
4
+ * Two surfaces:
5
+ * 1. Static templates (deterministic markdown rendering — see templates.ts)
6
+ * 2. AI SDK tools (agentic chat over the same data — see tools.ts)
7
+ *
8
+ * Both flow through the same aggregate.ts functions, so numbers are consistent.
9
+ */
10
+ export type { AggregateRow, CompareRunsResult, DimensionDelta, LongitudinalRow, ReportTemplate } from './types.js';
11
+ export { aggregateJob, leaderboard, longitudinalFor, compareRuns, tierBuckets } from './aggregate.js';
12
+ export type { LeaderboardOptions, TierBucket } from './aggregate.js';
13
+ export { renderLeaderboard, renderLongitudinal, renderBatchComparison, renderBrandEvolution, renderJobHeader, } from './templates.js';
14
+ export type { LeaderboardRenderOpts, LongitudinalRenderOpts, BatchComparisonRenderOpts, BrandEvolutionRenderOpts, } from './templates.js';
15
+ export { aggregateTokens, diffTokens, groupByUrl } from './tokens.js';
16
+ export type { TokenSummary, TokenDiff, TokenSeries } from './tokens.js';
17
+ export { buildReportTools } from './tools.js';
18
+ export type { ReportToolsContext, ReportToolSet } from './tools.js';
19
+ export { narrateReport } from './narrate.js';
20
+ export type { NarrateOptions } from './narrate.js';
21
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/reports/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,YAAY,EAAE,YAAY,EAAE,iBAAiB,EAAE,cAAc,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAClH,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,eAAe,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AACrG,YAAY,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AACpE,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,qBAAqB,EACrB,oBAAoB,EACpB,eAAe,GAChB,MAAM,gBAAgB,CAAA;AACvB,YAAY,EACV,qBAAqB,EACrB,sBAAsB,EACtB,yBAAyB,EACzB,wBAAwB,GACzB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACrE,YAAY,EAAE,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AACvE,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAC7C,YAAY,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AACnE,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAC5C,YAAY,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Reports — turn a job's audit results into shareable artifacts.
3
+ *
4
+ * Two surfaces:
5
+ * 1. Static templates (deterministic markdown rendering — see templates.ts)
6
+ * 2. AI SDK tools (agentic chat over the same data — see tools.ts)
7
+ *
8
+ * Both flow through the same aggregate.ts functions, so numbers are consistent.
9
+ */
10
+ export { aggregateJob, leaderboard, longitudinalFor, compareRuns, tierBuckets } from './aggregate.js';
11
+ export { renderLeaderboard, renderLongitudinal, renderBatchComparison, renderBrandEvolution, renderJobHeader, } from './templates.js';
12
+ export { aggregateTokens, diffTokens, groupByUrl } from './tokens.js';
13
+ export { buildReportTools } from './tools.js';
14
+ export { narrateReport } from './narrate.js';
15
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/reports/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,eAAe,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAErG,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,qBAAqB,EACrB,oBAAoB,EACpB,eAAe,GAChB,MAAM,gBAAgB,CAAA;AAOvB,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAErE,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAE7C,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * LLM narration around deterministic data.
3
+ *
4
+ * The contract: numbers come from the templates (which call the aggregate
5
+ * functions). The LLM only writes prose context — top-line takeaways, an
6
+ * angle on what's surprising. Same pattern as the patches contract.
7
+ *
8
+ * If a Brain isn't supplied, the deterministic markdown is returned as-is.
9
+ * That's the safe default — never silently fabricate prose.
10
+ */
11
+ import type { Brain } from '../brain/index.js';
12
+ export interface NarrateOptions {
13
+ /** When supplied, prepends an LLM-written executive summary above the deterministic body. */
14
+ brain?: Brain;
15
+ /** Free-form context passed to the LLM (e.g. "this is the YC W25 cohort"). */
16
+ context?: string;
17
+ }
18
+ export declare function narrateReport(deterministicMarkdown: string, opts?: NarrateOptions): Promise<string>;
19
+ //# sourceMappingURL=narrate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"narrate.d.ts","sourceRoot":"","sources":["../../src/reports/narrate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAU9C,MAAM,WAAW,cAAc;IAC7B,6FAA6F;IAC7F,KAAK,CAAC,EAAE,KAAK,CAAA;IACb,8EAA8E;IAC9E,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,wBAAsB,aAAa,CAAC,qBAAqB,EAAE,MAAM,EAAE,IAAI,GAAE,cAAmB,GAAG,OAAO,CAAC,MAAM,CAAC,CAkB7G"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * LLM narration around deterministic data.
3
+ *
4
+ * The contract: numbers come from the templates (which call the aggregate
5
+ * functions). The LLM only writes prose context — top-line takeaways, an
6
+ * angle on what's surprising. Same pattern as the patches contract.
7
+ *
8
+ * If a Brain isn't supplied, the deterministic markdown is returned as-is.
9
+ * That's the safe default — never silently fabricate prose.
10
+ */
11
+ const SYSTEM = `You are an analyst writing a one-paragraph executive summary at the top of a design-audit report.
12
+
13
+ Rules:
14
+ - Use ONLY the numbers and facts in the provided markdown report. Do not invent rankings, scores, or claims.
15
+ - Surface the most surprising or load-bearing finding (e.g. a tier-vs-tier gap, a dramatic longitudinal swing, an outlier).
16
+ - Two to four sentences. No bullet lists.
17
+ - Do not preface with "Here is your summary" or similar.`;
18
+ export async function narrateReport(deterministicMarkdown, opts = {}) {
19
+ if (!opts.brain)
20
+ return deterministicMarkdown;
21
+ const user = [
22
+ opts.context ? `Context: ${opts.context}` : undefined,
23
+ 'REPORT:',
24
+ deterministicMarkdown,
25
+ '',
26
+ 'Write the executive summary now.',
27
+ ].filter(Boolean).join('\n\n');
28
+ try {
29
+ const { text } = await opts.brain.complete(SYSTEM, user, { maxOutputTokens: 320 });
30
+ const summary = text.trim();
31
+ if (!summary)
32
+ return deterministicMarkdown;
33
+ return `## Executive summary\n\n${summary}\n\n${deterministicMarkdown}`;
34
+ }
35
+ catch {
36
+ // Don't let narration failures block the artifact. Ship the data.
37
+ return deterministicMarkdown;
38
+ }
39
+ }
40
+ //# sourceMappingURL=narrate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"narrate.js","sourceRoot":"","sources":["../../src/reports/narrate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,MAAM,MAAM,GAAG;;;;;;yDAM0C,CAAA;AASzD,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,qBAA6B,EAAE,OAAuB,EAAE;IAC1F,IAAI,CAAC,IAAI,CAAC,KAAK;QAAE,OAAO,qBAAqB,CAAA;IAC7C,MAAM,IAAI,GAAG;QACX,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,YAAY,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,SAAS;QACrD,SAAS;QACT,qBAAqB;QACrB,EAAE;QACF,kCAAkC;KACnC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IAC9B,IAAI,CAAC;QACH,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,EAAE,IAAI,EAAE,EAAE,eAAe,EAAE,GAAG,EAAE,CAAC,CAAA;QAClF,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAA;QAC3B,IAAI,CAAC,OAAO;YAAE,OAAO,qBAAqB,CAAA;QAC1C,OAAO,2BAA2B,OAAO,OAAO,qBAAqB,EAAE,CAAA;IACzE,CAAC;IAAC,MAAM,CAAC;QACP,kEAAkE;QAClE,OAAO,qBAAqB,CAAA;IAC9B,CAAC;AACH,CAAC"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Static report templates — markdown rendering of pre-aggregated data.
3
+ *
4
+ * No LLM. The narration layer (narrate.ts) wraps these with prose; the
5
+ * templates themselves are pure functions of data so they're snapshot-testable
6
+ * and deterministic.
7
+ */
8
+ import type { Job } from '../jobs/types.js';
9
+ import type { AggregateRow } from './types.js';
10
+ export interface LeaderboardRenderOpts {
11
+ title?: string;
12
+ topN?: number;
13
+ byType?: string;
14
+ /** Tier bucket boundaries — e.g. [10, 100, 200] → "top 10", "11–100", "101–200", "201+". */
15
+ buckets?: number[];
16
+ }
17
+ export declare function renderLeaderboard(rows: AggregateRow[], opts?: LeaderboardRenderOpts): string;
18
+ export interface LongitudinalRenderOpts {
19
+ title?: string;
20
+ /** If multiple URLs are in scope, render one section per URL. */
21
+ urls?: string[];
22
+ }
23
+ export declare function renderLongitudinal(rows: AggregateRow[], opts?: LongitudinalRenderOpts): string;
24
+ export interface BatchComparisonRenderOpts {
25
+ title?: string;
26
+ /** Pairs of (a, b) URLs to diff. If omitted, the first two URLs encountered are paired. */
27
+ pairs?: Array<[string, string]>;
28
+ }
29
+ export declare function renderBatchComparison(rows: AggregateRow[], opts?: BatchComparisonRenderOpts): string;
30
+ export interface BrandEvolutionRenderOpts {
31
+ title?: string;
32
+ /** Max colors to render per snapshot (top by usage count). Default 6. */
33
+ topColors?: number;
34
+ }
35
+ /**
36
+ * Render a per-URL brand-kit evolution: for each URL, list the snapshots in
37
+ * chronological order with their distinct color palette, font families, and
38
+ * detected libraries. Between consecutive snapshots, surface the delta
39
+ * (colors added/removed, families added/removed, brand-meta changes).
40
+ */
41
+ export declare function renderBrandEvolution(job: Job, opts?: BrandEvolutionRenderOpts): string;
42
+ export declare function renderJobHeader(job: Job): string;
43
+ //# sourceMappingURL=templates.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../../src/reports/templates.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAA;AAC3C,OAAO,KAAK,EAAE,YAAY,EAAmB,MAAM,YAAY,CAAA;AAI/D,MAAM,WAAW,qBAAqB;IACpC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,4FAA4F;IAC5F,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;CACnB;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,YAAY,EAAE,EAAE,IAAI,GAAE,qBAA0B,GAAG,MAAM,CAwChG;AAED,MAAM,WAAW,sBAAsB;IACrC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,iEAAiE;IACjE,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;CAChB;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,YAAY,EAAE,EAAE,IAAI,GAAE,sBAA2B,GAAG,MAAM,CA6BlG;AAED,MAAM,WAAW,yBAAyB;IACxC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,2FAA2F;IAC3F,KAAK,CAAC,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;CAChC;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,YAAY,EAAE,EAAE,IAAI,GAAE,yBAA8B,GAAG,MAAM,CA+BxG;AAED,MAAM,WAAW,wBAAwB;IACvC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,yEAAyE;IACzE,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,GAAE,wBAA6B,GAAG,MAAM,CAqD1F;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,GAAG,GAAG,MAAM,CAWhD"}
@@ -0,0 +1,200 @@
1
+ /**
2
+ * Static report templates — markdown rendering of pre-aggregated data.
3
+ *
4
+ * No LLM. The narration layer (narrate.ts) wraps these with prose; the
5
+ * templates themselves are pure functions of data so they're snapshot-testable
6
+ * and deterministic.
7
+ */
8
+ import { leaderboard, longitudinalFor, tierBuckets, compareRuns } from './aggregate.js';
9
+ import { aggregateTokens, diffTokens, groupByUrl } from './tokens.js';
10
+ export function renderLeaderboard(rows, opts = {}) {
11
+ const lines = [];
12
+ const title = opts.title ?? 'Design Audit Leaderboard';
13
+ lines.push(`# ${title}`);
14
+ lines.push('');
15
+ lines.push(`Generated: ${new Date().toISOString()}`);
16
+ lines.push('');
17
+ if (opts.byType) {
18
+ lines.push(`Filtered to page-type: \`${opts.byType}\``);
19
+ lines.push('');
20
+ }
21
+ const ranked = leaderboard(rows, { topN: opts.topN, byType: opts.byType });
22
+ lines.push(`## Ranked sites (${ranked.length})`);
23
+ lines.push('');
24
+ lines.push('| # | URL | Page type | Rollup | Top dim | Bottom dim | Ethics |');
25
+ lines.push('|---|-----|-----------|--------|---------|------------|--------|');
26
+ ranked.forEach((r, i) => {
27
+ const dims = Object.entries(r.dimensions);
28
+ dims.sort((a, b) => b[1] - a[1]);
29
+ const top = dims[0] ? `${dims[0][0]} ${dims[0][1].toFixed(1)}` : '—';
30
+ const bot = dims[dims.length - 1] ? `${dims[dims.length - 1][0]} ${dims[dims.length - 1][1].toFixed(1)}` : '—';
31
+ lines.push(`| ${i + 1} | ${escapeMd(r.url)} | ${r.pageType ?? '?'} | ${r.rollupScore.toFixed(2)} | ${top} | ${bot} | ${r.ethicsViolations} |`);
32
+ });
33
+ lines.push('');
34
+ if (opts.buckets && opts.buckets.length > 0) {
35
+ const buckets = tierBuckets(rows, opts.buckets);
36
+ lines.push('## Tiers');
37
+ lines.push('');
38
+ lines.push('| Tier | N | Mean | Median |');
39
+ lines.push('|------|---|------|--------|');
40
+ for (const b of buckets) {
41
+ lines.push(`| ${b.label} | ${b.rows.length} | ${fmt(b.meanScore)} | ${fmt(b.medianScore)} |`);
42
+ }
43
+ lines.push('');
44
+ }
45
+ return lines.join('\n');
46
+ }
47
+ export function renderLongitudinal(rows, opts = {}) {
48
+ const lines = [];
49
+ lines.push(`# ${opts.title ?? 'Longitudinal Design Audit'}`);
50
+ lines.push('');
51
+ lines.push(`Generated: ${new Date().toISOString()}`);
52
+ lines.push('');
53
+ const urls = opts.urls ?? Array.from(new Set(rows.map(r => r.url)));
54
+ for (const url of urls) {
55
+ const series = longitudinalFor(rows, url);
56
+ if (series.length === 0)
57
+ continue;
58
+ lines.push(`## ${escapeMd(url)}`);
59
+ lines.push('');
60
+ lines.push('| Captured | Rollup | Page type |');
61
+ lines.push('|----------|--------|-----------|');
62
+ for (const s of series) {
63
+ lines.push(`| ${s.capturedAt.slice(0, 10)} | ${s.rollupScore.toFixed(2)} | ${s.pageType ?? '?'} |`);
64
+ }
65
+ const first = series[0];
66
+ const last = series[series.length - 1];
67
+ if (first && last && first !== last) {
68
+ const delta = last.rollupScore - first.rollupScore;
69
+ const sign = delta >= 0 ? '+' : '';
70
+ lines.push('');
71
+ lines.push(`Net change ${first.capturedAt.slice(0, 10)} → ${last.capturedAt.slice(0, 10)}: **${sign}${delta.toFixed(2)}**`);
72
+ }
73
+ lines.push('');
74
+ }
75
+ return lines.join('\n');
76
+ }
77
+ export function renderBatchComparison(rows, opts = {}) {
78
+ const lines = [];
79
+ lines.push(`# ${opts.title ?? 'Batch Comparison'}`);
80
+ lines.push('');
81
+ lines.push(`Generated: ${new Date().toISOString()}`);
82
+ lines.push('');
83
+ let pairs = opts.pairs ?? [];
84
+ if (pairs.length === 0) {
85
+ const urls = Array.from(new Set(rows.map(r => r.url)));
86
+ if (urls.length >= 2)
87
+ pairs = [[urls[0], urls[1]]];
88
+ }
89
+ for (const [aUrl, bUrl] of pairs) {
90
+ const a = rows.find(r => r.url === aUrl && Number.isFinite(r.rollupScore));
91
+ const b = rows.find(r => r.url === bUrl && Number.isFinite(r.rollupScore));
92
+ if (!a || !b)
93
+ continue;
94
+ const cmp = compareRuns(a, b);
95
+ lines.push(`## ${escapeMd(aUrl)} vs ${escapeMd(bUrl)}`);
96
+ lines.push('');
97
+ lines.push(`Rollup delta: **${signed(cmp.rollupDelta)}** (a ${a.rollupScore.toFixed(2)} – b ${b.rollupScore.toFixed(2)})`);
98
+ lines.push('');
99
+ if (cmp.perDimension.length > 0) {
100
+ lines.push('| Dimension | a | b | Δ |');
101
+ lines.push('|-----------|---|---|---|');
102
+ for (const d of cmp.perDimension) {
103
+ lines.push(`| ${d.dim} | ${d.afterScore.toFixed(1)} | ${d.beforeScore.toFixed(1)} | ${signed(d.delta)} |`);
104
+ }
105
+ lines.push('');
106
+ }
107
+ }
108
+ return lines.join('\n');
109
+ }
110
+ /**
111
+ * Render a per-URL brand-kit evolution: for each URL, list the snapshots in
112
+ * chronological order with their distinct color palette, font families, and
113
+ * detected libraries. Between consecutive snapshots, surface the delta
114
+ * (colors added/removed, families added/removed, brand-meta changes).
115
+ */
116
+ export function renderBrandEvolution(job, opts = {}) {
117
+ const summaries = aggregateTokens(job);
118
+ const lines = [];
119
+ lines.push(`# ${opts.title ?? 'Brand & Design-System Evolution'}`);
120
+ lines.push('');
121
+ lines.push(`Generated: ${new Date().toISOString()}`);
122
+ lines.push('');
123
+ if (summaries.length === 0) {
124
+ lines.push(`_No tokens.json files were produced. Run the job with \`audit.extractTokens: true\` to enable._`);
125
+ return lines.join('\n');
126
+ }
127
+ const topColors = opts.topColors ?? 6;
128
+ const series = groupByUrl(summaries);
129
+ for (const { url, snapshots } of series) {
130
+ lines.push(`## ${escapeMd(url)}`);
131
+ lines.push('');
132
+ for (let i = 0; i < snapshots.length; i++) {
133
+ const s = snapshots[i];
134
+ const captured = s.capturedAt ? s.capturedAt.slice(0, 10) : 'live';
135
+ lines.push(`### ${captured}`);
136
+ lines.push('');
137
+ const swatches = s.colors.slice(0, topColors).map(c => `\`${c.hex}\` ×${c.count}`).join(' · ');
138
+ lines.push(`**Top colors**: ${swatches || '_none extracted_'}`);
139
+ const families = s.fontFamilies.map(f => `${f.family} (${f.classification})`).join(', ');
140
+ lines.push(`**Font families**: ${families || '_none_'}`);
141
+ lines.push(`**Type-scale entries**: ${s.typeScaleEntries}`);
142
+ if (s.detectedLibraries.length > 0)
143
+ lines.push(`**Detected libraries**: ${s.detectedLibraries.join(', ')}`);
144
+ if (s.brand?.themeColor)
145
+ lines.push(`**Theme color**: \`${s.brand.themeColor}\``);
146
+ if (s.logos.length > 0)
147
+ lines.push(`**Logos**: ${s.logos.length}`);
148
+ lines.push('');
149
+ // Snapshot-to-snapshot delta against the previous snapshot in the series.
150
+ const prev = snapshots[i - 1];
151
+ if (prev) {
152
+ const d = diffTokens(prev, s);
153
+ const callouts = [];
154
+ if (d.colorsAdded.length > 0)
155
+ callouts.push(`+${d.colorsAdded.length} new colors`);
156
+ if (d.colorsRemoved.length > 0)
157
+ callouts.push(`−${d.colorsRemoved.length} removed`);
158
+ if (d.familiesAdded.length > 0)
159
+ callouts.push(`+ ${d.familiesAdded.join(', ')}`);
160
+ if (d.familiesRemoved.length > 0)
161
+ callouts.push(`− ${d.familiesRemoved.join(', ')}`);
162
+ if (d.librariesAdded.length > 0)
163
+ callouts.push(`adopted ${d.librariesAdded.join(', ')}`);
164
+ if (d.librariesRemoved.length > 0)
165
+ callouts.push(`dropped ${d.librariesRemoved.join(', ')}`);
166
+ if (d.brandChanges.length > 0)
167
+ callouts.push(`brand meta: ${d.brandChanges.map(c => c.field).join(', ')} changed`);
168
+ if (callouts.length > 0) {
169
+ lines.push(`_Δ vs ${prev.capturedAt?.slice(0, 10) ?? 'previous'}: ${callouts.join(' · ')}_`);
170
+ lines.push('');
171
+ }
172
+ }
173
+ }
174
+ }
175
+ return lines.join('\n');
176
+ }
177
+ export function renderJobHeader(job) {
178
+ const ok = job.results.filter(r => r.status === 'ok').length;
179
+ const fail = job.results.filter(r => r.status === 'failed').length;
180
+ const skip = job.results.filter(r => r.status === 'skipped').length;
181
+ return [
182
+ `**Job**: \`${job.jobId}\``,
183
+ job.spec.label ? `**Label**: ${job.spec.label}` : undefined,
184
+ `**Targets**: ${job.targets.length} · ok: ${ok} · failed: ${fail} · skipped: ${skip}`,
185
+ `**Cost**: $${job.totalCostUSD.toFixed(2)}`,
186
+ `**Status**: ${job.status}`,
187
+ ].filter(Boolean).join(' \n');
188
+ }
189
+ function escapeMd(s) {
190
+ return s.replace(/\|/g, '\\|');
191
+ }
192
+ function signed(n) {
193
+ if (!Number.isFinite(n))
194
+ return '—';
195
+ return (n >= 0 ? '+' : '') + n.toFixed(2);
196
+ }
197
+ function fmt(n) {
198
+ return Number.isFinite(n) ? n.toFixed(2) : '—';
199
+ }
200
+ //# sourceMappingURL=templates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"templates.js","sourceRoot":"","sources":["../../src/reports/templates.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Brand-kit / design-token aggregation across a job's targets.
3
+ *
4
+ * Reads each per-target `tokens.json` (produced when AuditOptions.extractTokens
5
+ * was true) and projects to a flat row shape so longitudinal evolution and
6
+ * batch comparison templates can render without re-implementing extraction.
7
+ *
8
+ * No LLM. Pure function of on-disk data — same contract as aggregate.ts.
9
+ */
10
+ import type { Job } from '../jobs/types.js';
11
+ import type { DesignTokens, ColorToken, FontFamily } from '../types.js';
12
+ export interface TokenSummary {
13
+ /** Seed URL (groups snapshots of the same site). */
14
+ url: string;
15
+ /** Snapshot URL when wayback. */
16
+ snapshotUrl?: string;
17
+ /** ISO datetime of capture. */
18
+ capturedAt?: string;
19
+ /** Per-target runId (== outputDir for jobs). */
20
+ runId: string;
21
+ /** Resolved on-disk path to tokens.json. */
22
+ tokensPath?: string;
23
+ /** Top-level brand metadata (title, theme color, favicon, og image). */
24
+ brand: DesignTokens['brand'];
25
+ /** All distinct colors, sorted desc by usage count. */
26
+ colors: ColorToken[];
27
+ /** Distinct typography families with classification + weight set. */
28
+ fontFamilies: FontFamily[];
29
+ /** Type-scale entry count (proxy for typographic complexity). */
30
+ typeScaleEntries: number;
31
+ /** Logo asset URLs (svg + raster). */
32
+ logos: string[];
33
+ /** Loaded font-file URLs. */
34
+ fontFiles: string[];
35
+ /** Detected libraries (e.g. ['tailwind','radix-ui']). */
36
+ detectedLibraries: string[];
37
+ }
38
+ /** Read each ok result's tokens.json and project to TokenSummary. */
39
+ export declare function aggregateTokens(job: Job): TokenSummary[];
40
+ /**
41
+ * Diff between two TokenSummary records. Useful for "this URL evolved from
42
+ * 4 colors → 12 colors and dropped Helvetica for Inter" callouts.
43
+ */
44
+ export interface TokenDiff {
45
+ colorsAdded: string[];
46
+ colorsRemoved: string[];
47
+ colorsCommon: number;
48
+ familiesAdded: string[];
49
+ familiesRemoved: string[];
50
+ brandChanges: Array<{
51
+ field: keyof DesignTokens['brand'];
52
+ before: string | undefined;
53
+ after: string | undefined;
54
+ }>;
55
+ librariesAdded: string[];
56
+ librariesRemoved: string[];
57
+ }
58
+ export declare function diffTokens(a: TokenSummary, b: TokenSummary): TokenDiff;
59
+ /**
60
+ * Group token summaries by URL and return a chronological evolution series.
61
+ * Returns one entry per URL; each carries the sequence of TokenSummary rows
62
+ * sorted by capturedAt (or insertion order when capturedAt is missing).
63
+ */
64
+ export interface TokenSeries {
65
+ url: string;
66
+ snapshots: TokenSummary[];
67
+ }
68
+ export declare function groupByUrl(summaries: TokenSummary[]): TokenSeries[];
69
+ //# sourceMappingURL=tokens.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../../src/reports/tokens.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAA;AAC3C,OAAO,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAEvE,MAAM,WAAW,YAAY;IAC3B,oDAAoD;IACpD,GAAG,EAAE,MAAM,CAAA;IACX,iCAAiC;IACjC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,+BAA+B;IAC/B,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,gDAAgD;IAChD,KAAK,EAAE,MAAM,CAAA;IACb,4CAA4C;IAC5C,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,wEAAwE;IACxE,KAAK,EAAE,YAAY,CAAC,OAAO,CAAC,CAAA;IAC5B,uDAAuD;IACvD,MAAM,EAAE,UAAU,EAAE,CAAA;IACpB,qEAAqE;IACrE,YAAY,EAAE,UAAU,EAAE,CAAA;IAC1B,iEAAiE;IACjE,gBAAgB,EAAE,MAAM,CAAA;IACxB,sCAAsC;IACtC,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,6BAA6B;IAC7B,SAAS,EAAE,MAAM,EAAE,CAAA;IACnB,yDAAyD;IACzD,iBAAiB,EAAE,MAAM,EAAE,CAAA;CAC5B;AAED,qEAAqE;AACrE,wBAAgB,eAAe,CAAC,GAAG,EAAE,GAAG,GAAG,YAAY,EAAE,CAyBxD;AAED;;;GAGG;AACH,MAAM,WAAW,SAAS;IACxB,WAAW,EAAE,MAAM,EAAE,CAAA;IACrB,aAAa,EAAE,MAAM,EAAE,CAAA;IACvB,YAAY,EAAE,MAAM,CAAA;IACpB,aAAa,EAAE,MAAM,EAAE,CAAA;IACvB,eAAe,EAAE,MAAM,EAAE,CAAA;IACzB,YAAY,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,YAAY,CAAC,OAAO,CAAC,CAAC;QAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;QAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,CAAC,CAAA;IAClH,cAAc,EAAE,MAAM,EAAE,CAAA;IACxB,gBAAgB,EAAE,MAAM,EAAE,CAAA;CAC3B;AAED,wBAAgB,UAAU,CAAC,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,YAAY,GAAG,SAAS,CAuBtE;AAED;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAA;IACX,SAAS,EAAE,YAAY,EAAE,CAAA;CAC1B;AAED,wBAAgB,UAAU,CAAC,SAAS,EAAE,YAAY,EAAE,GAAG,WAAW,EAAE,CAYnE"}