@tangle-network/browser-agent-driver 0.29.0 → 0.31.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 (276) hide show
  1. package/dist/brain/index.d.ts +15 -1
  2. package/dist/brain/index.d.ts.map +1 -1
  3. package/dist/brain/index.js +67 -5
  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 +16 -0
  10. package/dist/cli-design-audit.d.ts.map +1 -1
  11. package/dist/cli-design-audit.js +232 -7
  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 +262 -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-ui.d.ts.map +1 -1
  26. package/dist/cli-ui.js +5 -1
  27. package/dist/cli-ui.js.map +1 -1
  28. package/dist/cli.js +52 -2
  29. package/dist/cli.js.map +1 -1
  30. package/dist/config.d.ts +4 -4
  31. package/dist/config.d.ts.map +1 -1
  32. package/dist/design/audit/attribution/aggregate.d.ts +16 -0
  33. package/dist/design/audit/attribution/aggregate.d.ts.map +1 -0
  34. package/dist/design/audit/attribution/aggregate.js +81 -0
  35. package/dist/design/audit/attribution/aggregate.js.map +1 -0
  36. package/dist/design/audit/attribution/store.d.ts +36 -0
  37. package/dist/design/audit/attribution/store.d.ts.map +1 -0
  38. package/dist/design/audit/attribution/store.js +108 -0
  39. package/dist/design/audit/attribution/store.js.map +1 -0
  40. package/dist/design/audit/attribution/types.d.ts +13 -0
  41. package/dist/design/audit/attribution/types.d.ts.map +1 -0
  42. package/dist/design/audit/attribution/types.js +10 -0
  43. package/dist/design/audit/attribution/types.js.map +1 -0
  44. package/dist/design/audit/classify-ensemble.d.ts +46 -0
  45. package/dist/design/audit/classify-ensemble.d.ts.map +1 -0
  46. package/dist/design/audit/classify-ensemble.js +207 -0
  47. package/dist/design/audit/classify-ensemble.js.map +1 -0
  48. package/dist/design/audit/ethics/check.d.ts +59 -0
  49. package/dist/design/audit/ethics/check.d.ts.map +1 -0
  50. package/dist/design/audit/ethics/check.js +137 -0
  51. package/dist/design/audit/ethics/check.js.map +1 -0
  52. package/dist/design/audit/ethics/loader.d.ts +21 -0
  53. package/dist/design/audit/ethics/loader.d.ts.map +1 -0
  54. package/dist/design/audit/ethics/loader.js +207 -0
  55. package/dist/design/audit/ethics/loader.js.map +1 -0
  56. package/dist/design/audit/ethics/rules/finance.yaml +37 -0
  57. package/dist/design/audit/ethics/rules/kids.yaml +37 -0
  58. package/dist/design/audit/ethics/rules/legal.yaml +35 -0
  59. package/dist/design/audit/ethics/rules/medical.yaml +36 -0
  60. package/dist/design/audit/evaluate.d.ts +69 -0
  61. package/dist/design/audit/evaluate.d.ts.map +1 -1
  62. package/dist/design/audit/evaluate.js +417 -55
  63. package/dist/design/audit/evaluate.js.map +1 -1
  64. package/dist/design/audit/first-principles-mode.d.ts +42 -0
  65. package/dist/design/audit/first-principles-mode.d.ts.map +1 -0
  66. package/dist/design/audit/first-principles-mode.js +77 -0
  67. package/dist/design/audit/first-principles-mode.js.map +1 -0
  68. package/dist/design/audit/modality/android.d.ts +14 -0
  69. package/dist/design/audit/modality/android.d.ts.map +1 -0
  70. package/dist/design/audit/modality/android.js +18 -0
  71. package/dist/design/audit/modality/android.js.map +1 -0
  72. package/dist/design/audit/modality/html.d.ts +22 -0
  73. package/dist/design/audit/modality/html.d.ts.map +1 -0
  74. package/dist/design/audit/modality/html.js +51 -0
  75. package/dist/design/audit/modality/html.js.map +1 -0
  76. package/dist/design/audit/modality/index.d.ts +8 -0
  77. package/dist/design/audit/modality/index.d.ts.map +1 -0
  78. package/dist/design/audit/modality/index.js +15 -0
  79. package/dist/design/audit/modality/index.js.map +1 -0
  80. package/dist/design/audit/modality/ios.d.ts +16 -0
  81. package/dist/design/audit/modality/ios.d.ts.map +1 -0
  82. package/dist/design/audit/modality/ios.js +19 -0
  83. package/dist/design/audit/modality/ios.js.map +1 -0
  84. package/dist/design/audit/modality/types.d.ts +9 -0
  85. package/dist/design/audit/modality/types.d.ts.map +1 -0
  86. package/dist/design/audit/modality/types.js +9 -0
  87. package/dist/design/audit/modality/types.js.map +1 -0
  88. package/dist/design/audit/patches/index.d.ts +8 -0
  89. package/dist/design/audit/patches/index.d.ts.map +1 -0
  90. package/dist/design/audit/patches/index.js +5 -0
  91. package/dist/design/audit/patches/index.js.map +1 -0
  92. package/dist/design/audit/patches/parse.d.ts +29 -0
  93. package/dist/design/audit/patches/parse.d.ts.map +1 -0
  94. package/dist/design/audit/patches/parse.js +153 -0
  95. package/dist/design/audit/patches/parse.js.map +1 -0
  96. package/dist/design/audit/patches/render.d.ts +20 -0
  97. package/dist/design/audit/patches/render.d.ts.map +1 -0
  98. package/dist/design/audit/patches/render.js +55 -0
  99. package/dist/design/audit/patches/render.js.map +1 -0
  100. package/dist/design/audit/patches/severity-enforcement.d.ts +23 -0
  101. package/dist/design/audit/patches/severity-enforcement.d.ts.map +1 -0
  102. package/dist/design/audit/patches/severity-enforcement.js +42 -0
  103. package/dist/design/audit/patches/severity-enforcement.js.map +1 -0
  104. package/dist/design/audit/patches/validate.d.ts +34 -0
  105. package/dist/design/audit/patches/validate.d.ts.map +1 -0
  106. package/dist/design/audit/patches/validate.js +53 -0
  107. package/dist/design/audit/patches/validate.js.map +1 -0
  108. package/dist/design/audit/patterns/match.d.ts +24 -0
  109. package/dist/design/audit/patterns/match.d.ts.map +1 -0
  110. package/dist/design/audit/patterns/match.js +48 -0
  111. package/dist/design/audit/patterns/match.js.map +1 -0
  112. package/dist/design/audit/patterns/mine.d.ts +31 -0
  113. package/dist/design/audit/patterns/mine.d.ts.map +1 -0
  114. package/dist/design/audit/patterns/mine.js +35 -0
  115. package/dist/design/audit/patterns/mine.js.map +1 -0
  116. package/dist/design/audit/patterns/store.d.ts +14 -0
  117. package/dist/design/audit/patterns/store.d.ts.map +1 -0
  118. package/dist/design/audit/patterns/store.js +53 -0
  119. package/dist/design/audit/patterns/store.js.map +1 -0
  120. package/dist/design/audit/patterns/types.d.ts +53 -0
  121. package/dist/design/audit/patterns/types.d.ts.map +1 -0
  122. package/dist/design/audit/patterns/types.js +13 -0
  123. package/dist/design/audit/patterns/types.js.map +1 -0
  124. package/dist/design/audit/pipeline.d.ts +26 -0
  125. package/dist/design/audit/pipeline.d.ts.map +1 -1
  126. package/dist/design/audit/pipeline.js +131 -4
  127. package/dist/design/audit/pipeline.js.map +1 -1
  128. package/dist/design/audit/rubric/anchor-loader.d.ts +44 -0
  129. package/dist/design/audit/rubric/anchor-loader.d.ts.map +1 -0
  130. package/dist/design/audit/rubric/anchor-loader.js +210 -0
  131. package/dist/design/audit/rubric/anchor-loader.js.map +1 -0
  132. package/dist/design/audit/rubric/anchors/blog.yaml +33 -0
  133. package/dist/design/audit/rubric/anchors/dashboard.yaml +35 -0
  134. package/dist/design/audit/rubric/anchors/docs.yaml +35 -0
  135. package/dist/design/audit/rubric/anchors/ecommerce.yaml +33 -0
  136. package/dist/design/audit/rubric/anchors/marketing.yaml +34 -0
  137. package/dist/design/audit/rubric/anchors/saas-app.yaml +38 -0
  138. package/dist/design/audit/rubric/anchors/social.yaml +33 -0
  139. package/dist/design/audit/rubric/anchors/tool.yaml +33 -0
  140. package/dist/design/audit/rubric/anchors/utility.yaml +33 -0
  141. package/dist/design/audit/rubric/fragments/audience-clinician.md +42 -0
  142. package/dist/design/audit/rubric/fragments/audience-developer.md +40 -0
  143. package/dist/design/audit/rubric/fragments/audience-kids.md +35 -0
  144. package/dist/design/audit/rubric/fragments/audience-vulnerability-minor-facing.md +37 -0
  145. package/dist/design/audit/rubric/fragments/first-principles.md +65 -0
  146. package/dist/design/audit/rubric/fragments/modality-mobile.md +39 -0
  147. package/dist/design/audit/rubric/fragments/modality-tablet.md +35 -0
  148. package/dist/design/audit/rubric/fragments/regulatory-coppa.md +32 -0
  149. package/dist/design/audit/rubric/fragments/regulatory-gdpr.md +33 -0
  150. package/dist/design/audit/rubric/fragments/regulatory-hipaa.md +36 -0
  151. package/dist/design/audit/rubric/fragments/universal-product-intent.md +48 -0
  152. package/dist/design/audit/rubric/loader.d.ts +26 -6
  153. package/dist/design/audit/rubric/loader.d.ts.map +1 -1
  154. package/dist/design/audit/rubric/loader.js +77 -27
  155. package/dist/design/audit/rubric/loader.js.map +1 -1
  156. package/dist/design/audit/rubric/rollup-weights.d.ts +25 -0
  157. package/dist/design/audit/rubric/rollup-weights.d.ts.map +1 -0
  158. package/dist/design/audit/rubric/rollup-weights.js +51 -0
  159. package/dist/design/audit/rubric/rollup-weights.js.map +1 -0
  160. package/dist/design/audit/types.d.ts +28 -0
  161. package/dist/design/audit/types.d.ts.map +1 -1
  162. package/dist/design/audit/v2/build-result.d.ts +47 -0
  163. package/dist/design/audit/v2/build-result.d.ts.map +1 -0
  164. package/dist/design/audit/v2/build-result.js +163 -0
  165. package/dist/design/audit/v2/build-result.js.map +1 -0
  166. package/dist/design/audit/v2/score.d.ts +49 -0
  167. package/dist/design/audit/v2/score.d.ts.map +1 -0
  168. package/dist/design/audit/v2/score.js +211 -0
  169. package/dist/design/audit/v2/score.js.map +1 -0
  170. package/dist/design/audit/v2/types.d.ts +431 -0
  171. package/dist/design/audit/v2/types.d.ts.map +1 -0
  172. package/dist/design/audit/v2/types.js +26 -0
  173. package/dist/design/audit/v2/types.js.map +1 -0
  174. package/dist/discover/index.d.ts +16 -0
  175. package/dist/discover/index.d.ts.map +1 -0
  176. package/dist/discover/index.js +25 -0
  177. package/dist/discover/index.js.map +1 -0
  178. package/dist/discover/wayback.d.ts +49 -0
  179. package/dist/discover/wayback.d.ts.map +1 -0
  180. package/dist/discover/wayback.js +123 -0
  181. package/dist/discover/wayback.js.map +1 -0
  182. package/dist/jobs/anti-bot.d.ts +19 -0
  183. package/dist/jobs/anti-bot.d.ts.map +1 -0
  184. package/dist/jobs/anti-bot.js +64 -0
  185. package/dist/jobs/anti-bot.js.map +1 -0
  186. package/dist/jobs/cost-estimate.d.ts +12 -0
  187. package/dist/jobs/cost-estimate.d.ts.map +1 -0
  188. package/dist/jobs/cost-estimate.js +21 -0
  189. package/dist/jobs/cost-estimate.js.map +1 -0
  190. package/dist/jobs/cost-history.d.ts +19 -0
  191. package/dist/jobs/cost-history.d.ts.map +1 -0
  192. package/dist/jobs/cost-history.js +42 -0
  193. package/dist/jobs/cost-history.js.map +1 -0
  194. package/dist/jobs/index.d.ts +31 -0
  195. package/dist/jobs/index.d.ts.map +1 -0
  196. package/dist/jobs/index.js +37 -0
  197. package/dist/jobs/index.js.map +1 -0
  198. package/dist/jobs/orchestrator.d.ts +42 -0
  199. package/dist/jobs/orchestrator.d.ts.map +1 -0
  200. package/dist/jobs/orchestrator.js +282 -0
  201. package/dist/jobs/orchestrator.js.map +1 -0
  202. package/dist/jobs/queue.d.ts +45 -0
  203. package/dist/jobs/queue.d.ts.map +1 -0
  204. package/dist/jobs/queue.js +114 -0
  205. package/dist/jobs/queue.js.map +1 -0
  206. package/dist/jobs/retry.d.ts +36 -0
  207. package/dist/jobs/retry.d.ts.map +1 -0
  208. package/dist/jobs/retry.js +77 -0
  209. package/dist/jobs/retry.js.map +1 -0
  210. package/dist/jobs/store.d.ts +31 -0
  211. package/dist/jobs/store.d.ts.map +1 -0
  212. package/dist/jobs/store.js +92 -0
  213. package/dist/jobs/store.js.map +1 -0
  214. package/dist/jobs/types.d.ts +106 -0
  215. package/dist/jobs/types.d.ts.map +1 -0
  216. package/dist/jobs/types.js +13 -0
  217. package/dist/jobs/types.js.map +1 -0
  218. package/dist/provider-defaults.d.ts +1 -1
  219. package/dist/provider-defaults.d.ts.map +1 -1
  220. package/dist/provider-defaults.js +8 -0
  221. package/dist/provider-defaults.js.map +1 -1
  222. package/dist/reports/aggregate.d.ts +38 -0
  223. package/dist/reports/aggregate.d.ts.map +1 -0
  224. package/dist/reports/aggregate.js +145 -0
  225. package/dist/reports/aggregate.js.map +1 -0
  226. package/dist/reports/index.d.ts +21 -0
  227. package/dist/reports/index.d.ts.map +1 -0
  228. package/dist/reports/index.js +15 -0
  229. package/dist/reports/index.js.map +1 -0
  230. package/dist/reports/narrate.d.ts +19 -0
  231. package/dist/reports/narrate.d.ts.map +1 -0
  232. package/dist/reports/narrate.js +40 -0
  233. package/dist/reports/narrate.js.map +1 -0
  234. package/dist/reports/templates.d.ts +43 -0
  235. package/dist/reports/templates.d.ts.map +1 -0
  236. package/dist/reports/templates.js +200 -0
  237. package/dist/reports/templates.js.map +1 -0
  238. package/dist/reports/tokens.d.ts +77 -0
  239. package/dist/reports/tokens.d.ts.map +1 -0
  240. package/dist/reports/tokens.js +88 -0
  241. package/dist/reports/tokens.js.map +1 -0
  242. package/dist/reports/tools.d.ts +76 -0
  243. package/dist/reports/tools.d.ts.map +1 -0
  244. package/dist/reports/tools.js +205 -0
  245. package/dist/reports/tools.js.map +1 -0
  246. package/dist/reports/types.d.ts +51 -0
  247. package/dist/reports/types.d.ts.map +1 -0
  248. package/dist/reports/types.js +9 -0
  249. package/dist/reports/types.js.map +1 -0
  250. package/dist/supervisor/critic.d.ts +1 -1
  251. package/dist/supervisor/critic.d.ts.map +1 -1
  252. package/dist/supervisor/critic.js +50 -5
  253. package/dist/supervisor/critic.js.map +1 -1
  254. package/dist/telemetry/client.d.ts +42 -0
  255. package/dist/telemetry/client.d.ts.map +1 -0
  256. package/dist/telemetry/client.js +203 -0
  257. package/dist/telemetry/client.js.map +1 -0
  258. package/dist/telemetry/hash.d.ts +4 -0
  259. package/dist/telemetry/hash.d.ts.map +1 -0
  260. package/dist/telemetry/hash.js +7 -0
  261. package/dist/telemetry/hash.js.map +1 -0
  262. package/dist/telemetry/index.d.ts +6 -0
  263. package/dist/telemetry/index.d.ts.map +1 -0
  264. package/dist/telemetry/index.js +5 -0
  265. package/dist/telemetry/index.js.map +1 -0
  266. package/dist/telemetry/schema.d.ts +85 -0
  267. package/dist/telemetry/schema.d.ts.map +1 -0
  268. package/dist/telemetry/schema.js +13 -0
  269. package/dist/telemetry/schema.js.map +1 -0
  270. package/dist/telemetry/sink.d.ts +46 -0
  271. package/dist/telemetry/sink.d.ts.map +1 -0
  272. package/dist/telemetry/sink.js +97 -0
  273. package/dist/telemetry/sink.js.map +1 -0
  274. package/dist/types.d.ts +5 -5
  275. package/dist/types.d.ts.map +1 -1
  276. package/package.json +5 -1
@@ -7,10 +7,16 @@
7
7
  * a pure function elsewhere in this module — easy to unit test in isolation.
8
8
  */
9
9
  import * as path from 'node:path';
10
- import { classifyPage, defaultClassification } from './classify.js';
10
+ import { defaultClassification } from './classify.js';
11
11
  import { composeRubric, composeRubricFromProfile } from './rubric/loader.js';
12
12
  import { gatherMeasurements } from './measure/index.js';
13
13
  import { evaluatePage } from './evaluate.js';
14
+ import { getTelemetry, shortHash } from '../../telemetry/index.js';
15
+ import { loadEthicsRules } from './ethics/loader.js';
16
+ import { checkEthics, pageTextBlob } from './ethics/check.js';
17
+ import { classifyEnsemble } from './classify-ensemble.js';
18
+ import { loadAnchors } from './rubric/anchor-loader.js';
19
+ import { buildAuditResultV2 } from './v2/build-result.js';
14
20
  const COOKIE_BANNER_SELECTORS = [
15
21
  'button:has-text("Accept all")',
16
22
  'button:has-text("Accept")',
@@ -32,7 +38,8 @@ async function dismissCookieBanners(page) {
32
38
  * Audit one page through the full Gen 2 pipeline.
33
39
  */
34
40
  export async function auditOnePage(opts) {
35
- const { brain, driver, page, url, profileOverride, screenshotDir, userRubricsDir } = opts;
41
+ const { brain, driver, page, url, profileOverride, screenshotDir, userRubricsDir, auditPasses, runId, parentRunId, provider, model, overrides, skipEthics, ethicsRulesDir, audience, modality, regulatoryContext, audienceVulnerability, } = opts;
42
+ const startedAt = Date.now();
36
43
  try {
37
44
  // ── 1. Load the page ──
38
45
  await page
@@ -49,7 +56,9 @@ export async function auditOnePage(opts) {
49
56
  await page.screenshot({ path: screenshotPath, fullPage: false });
50
57
  }
51
58
  // ── 3. Classify (or use profile override) ──
59
+ // Layer 1: ensemble classifier (URL + DOM + LLM) when no override is set.
52
60
  let classification;
61
+ let ensemble;
53
62
  if (profileOverride) {
54
63
  // Build a synthetic classification matching the explicit profile
55
64
  classification = {
@@ -59,7 +68,8 @@ export async function auditOnePage(opts) {
59
68
  };
60
69
  }
61
70
  else {
62
- classification = await classifyPage(brain, state);
71
+ ensemble = await classifyEnsemble({ brain, state, url });
72
+ classification = ensemble;
63
73
  }
64
74
  // ── 4. Compose rubric ──
65
75
  const rubric = profileOverride
@@ -84,17 +94,134 @@ export async function auditOnePage(opts) {
84
94
  rubric,
85
95
  measurements,
86
96
  screenshotPath,
97
+ auditPasses,
98
+ overrides,
87
99
  });
100
+ // ── 7. Ethics gate (Layer 7) — apply rollup floor when rules fire ──
101
+ if (skipEthics) {
102
+ console.warn(`[ethics] --skip-ethics: gate bypassed for ${url} (test-only)`);
103
+ result.ethicsViolations = [];
104
+ }
105
+ else {
106
+ const rules = loadEthicsRules(ethicsRulesDir);
107
+ const ethicsViolations = await checkEthics(rules, {
108
+ pageText: pageTextBlob(state.snapshot, { url, title: state.title }),
109
+ snapshot: state.snapshot,
110
+ classification,
111
+ audience,
112
+ modality,
113
+ regulatoryContext,
114
+ audienceVulnerability,
115
+ }, { brain });
116
+ if (ethicsViolations.length > 0) {
117
+ const minCap = Math.min(...ethicsViolations.map((v) => v.rollupCap));
118
+ if (typeof result.score === 'number' && result.score > minCap) {
119
+ result.preEthicsScore = result.score;
120
+ result.score = minCap;
121
+ }
122
+ }
123
+ result.ethicsViolations = ethicsViolations;
124
+ }
125
+ // ── 8. Layer 1 v2 — multi-dim scoring + rollup, emitted alongside v1 ──
126
+ if (ensemble) {
127
+ try {
128
+ const anchors = loadAnchors();
129
+ const anchor = anchors.get(ensemble.type);
130
+ const v2 = await buildAuditResultV2({
131
+ brain,
132
+ state,
133
+ pageRef: url,
134
+ ensemble,
135
+ rubric,
136
+ measurements,
137
+ v1Result: result,
138
+ anchor,
139
+ runId,
140
+ });
141
+ result.auditResultV2 = v2;
142
+ result.ensembleClassification = ensemble;
143
+ }
144
+ catch (v2Err) {
145
+ // Don't let v2 failures break v1. Log + move on.
146
+ console.warn(`[audit/v2] failed to build v2 result for ${url}: ${v2Err.message}`);
147
+ }
148
+ }
149
+ if (runId) {
150
+ const findings = result.findings ?? [];
151
+ const ethicsViolations = result.ethicsViolations ?? [];
152
+ getTelemetry().emit({
153
+ kind: 'design-audit-page',
154
+ runId,
155
+ parentRunId,
156
+ ok: !result.error,
157
+ durationMs: Date.now() - startedAt,
158
+ ...(provider && model ? { model: { provider, name: model, rubricHash: shortHash(rubric.body) } } : {}),
159
+ data: {
160
+ url,
161
+ classification,
162
+ rubricFragments: rubric.fragments.map((f) => f.id),
163
+ rubricDimensions: rubric.dimensions,
164
+ auditPasses: auditPasses ?? ['standard'],
165
+ designSystemScore: result.designSystemScore,
166
+ summary: result.summary,
167
+ strengths: result.strengths,
168
+ findings: findings.map((f) => ({
169
+ category: f.category,
170
+ severity: f.severity,
171
+ description: f.description,
172
+ location: f.location,
173
+ cssSelector: f.cssSelector,
174
+ impact: f.impact,
175
+ effort: f.effort,
176
+ blast: f.blast,
177
+ })),
178
+ },
179
+ metrics: {
180
+ score: result.score,
181
+ findingCount: findings.length,
182
+ criticalCount: findings.filter((f) => f.severity === 'critical').length,
183
+ majorCount: findings.filter((f) => f.severity === 'major').length,
184
+ minorCount: findings.filter((f) => f.severity === 'minor').length,
185
+ contrastAaPassRate: measurements.contrast.summary.aaPassRate,
186
+ a11yViolations: measurements.a11y.violations.length,
187
+ tokensUsed: result.tokensUsed ?? 0,
188
+ ethicsViolations: ethicsViolations.length,
189
+ ethicsCriticalFloor: ethicsViolations.filter((v) => v.severity === 'critical-floor').length,
190
+ ethicsMajorFloor: ethicsViolations.filter((v) => v.severity === 'major-floor').length,
191
+ },
192
+ tags: {
193
+ pageType: classification.type,
194
+ domain: classification.domain,
195
+ maturity: classification.maturity,
196
+ designSystem: classification.designSystem,
197
+ },
198
+ });
199
+ }
88
200
  return result;
89
201
  }
90
202
  catch (err) {
203
+ const error = err instanceof Error ? err.message : String(err);
204
+ if (runId) {
205
+ getTelemetry().emit({
206
+ kind: 'design-audit-page',
207
+ runId,
208
+ parentRunId,
209
+ ok: false,
210
+ durationMs: Date.now() - startedAt,
211
+ ...(provider && model ? { model: { provider, name: model } } : {}),
212
+ data: { url },
213
+ metrics: { score: 0, findingCount: 0 },
214
+ error,
215
+ });
216
+ }
91
217
  return {
92
218
  url,
93
219
  score: 0,
94
220
  summary: 'Audit failed',
95
221
  strengths: [],
96
222
  findings: [],
97
- error: err instanceof Error ? err.message : String(err),
223
+ ethicsViolations: [],
224
+ error,
98
225
  };
99
226
  }
100
227
  }
@@ -1 +1 @@
1
- {"version":3,"file":"pipeline.js","sourceRoot":"","sources":["../../../src/design/audit/pipeline.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"pipeline.js","sourceRoot":"","sources":["../../../src/design/audit/pipeline.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Anchor loader — Layer 1 of the world-class design-audit architecture.
3
+ *
4
+ * Loads per-page-type calibration anchors from `anchors/<type>.yaml`. Each
5
+ * anchor encodes score-band criteria + reference fixtures so the LLM scores
6
+ * an saas-app like Linear's app, not like Linear's marketing site.
7
+ *
8
+ * Schema:
9
+ * type: <PageType>
10
+ * score_9_10: { criteria: string[], fixtures: string[] }
11
+ * score_7_8: { criteria: string[], fixtures: string[] }
12
+ * score_5_6: { criteria: string[], fixtures: string[] }
13
+ * score_3_4: { criteria: string[], fixtures: string[] }
14
+ */
15
+ import type { PageType } from '../types.js';
16
+ export interface AnchorBand {
17
+ criteria: string[];
18
+ fixtures: string[];
19
+ }
20
+ export interface CalibrationAnchor {
21
+ type: PageType;
22
+ score_9_10: AnchorBand;
23
+ score_7_8: AnchorBand;
24
+ score_5_6: AnchorBand;
25
+ score_3_4: AnchorBand;
26
+ }
27
+ /**
28
+ * Parse one anchor YAML. Uses a minimal YAML reader that handles the shape:
29
+ * type: saas-app
30
+ * score_9_10:
31
+ * criteria:
32
+ * - line one
33
+ * - line two
34
+ * fixtures:
35
+ * - fixture:linear-app
36
+ *
37
+ * Avoids pulling in a YAML dep for ~9 small files. Throws on malformed input.
38
+ */
39
+ export declare function parseAnchorFile(filePath: string): CalibrationAnchor;
40
+ /** Load all anchors from `anchors/` into a map keyed by PageType. */
41
+ export declare function loadAnchors(dir?: string): Map<PageType, CalibrationAnchor>;
42
+ /** Render an anchor as a markdown block for prompt injection. */
43
+ export declare function renderAnchor(anchor: CalibrationAnchor): string;
44
+ //# sourceMappingURL=anchor-loader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anchor-loader.d.ts","sourceRoot":"","sources":["../../../../src/design/audit/rubric/anchor-loader.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAKH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAK3C,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB,QAAQ,EAAE,MAAM,EAAE,CAAA;CACnB;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,QAAQ,CAAA;IACd,UAAU,EAAE,UAAU,CAAA;IACtB,SAAS,EAAE,UAAU,CAAA;IACrB,SAAS,EAAE,UAAU,CAAA;IACrB,SAAS,EAAE,UAAU,CAAA;CACtB;AAID;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,iBAAiB,CAuBnE;AAED,qEAAqE;AACrE,wBAAgB,WAAW,CAAC,GAAG,GAAE,MAAoB,GAAG,GAAG,CAAC,QAAQ,EAAE,iBAAiB,CAAC,CASvF;AAED,iEAAiE;AACjE,wBAAgB,YAAY,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,CAU9D"}
@@ -0,0 +1,210 @@
1
+ /**
2
+ * Anchor loader — Layer 1 of the world-class design-audit architecture.
3
+ *
4
+ * Loads per-page-type calibration anchors from `anchors/<type>.yaml`. Each
5
+ * anchor encodes score-band criteria + reference fixtures so the LLM scores
6
+ * an saas-app like Linear's app, not like Linear's marketing site.
7
+ *
8
+ * Schema:
9
+ * type: <PageType>
10
+ * score_9_10: { criteria: string[], fixtures: string[] }
11
+ * score_7_8: { criteria: string[], fixtures: string[] }
12
+ * score_5_6: { criteria: string[], fixtures: string[] }
13
+ * score_3_4: { criteria: string[], fixtures: string[] }
14
+ */
15
+ import * as fs from 'node:fs';
16
+ import * as path from 'node:path';
17
+ import { fileURLToPath } from 'node:url';
18
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
19
+ const ANCHORS_DIR = path.join(__dirname, 'anchors');
20
+ const REQUIRED_BANDS = ['score_9_10', 'score_7_8', 'score_5_6', 'score_3_4'];
21
+ /**
22
+ * Parse one anchor YAML. Uses a minimal YAML reader that handles the shape:
23
+ * type: saas-app
24
+ * score_9_10:
25
+ * criteria:
26
+ * - line one
27
+ * - line two
28
+ * fixtures:
29
+ * - fixture:linear-app
30
+ *
31
+ * Avoids pulling in a YAML dep for ~9 small files. Throws on malformed input.
32
+ */
33
+ export function parseAnchorFile(filePath) {
34
+ const raw = fs.readFileSync(filePath, 'utf-8');
35
+ const parsed = parseAnchorYaml(raw);
36
+ if (!parsed.type || typeof parsed.type !== 'string') {
37
+ throw new Error(`anchor ${filePath} missing 'type' field`);
38
+ }
39
+ for (const band of REQUIRED_BANDS) {
40
+ const node = parsed[band];
41
+ if (!node || typeof node !== 'object') {
42
+ throw new Error(`anchor ${filePath} missing '${band}' band`);
43
+ }
44
+ const b = node;
45
+ if (!Array.isArray(b.criteria) || b.criteria.length === 0) {
46
+ throw new Error(`anchor ${filePath} '${band}.criteria' must be a non-empty array`);
47
+ }
48
+ if (!Array.isArray(b.fixtures) || b.fixtures.length === 0) {
49
+ throw new Error(`anchor ${filePath} '${band}.fixtures' must be a non-empty array`);
50
+ }
51
+ }
52
+ return parsed;
53
+ }
54
+ /** Load all anchors from `anchors/` into a map keyed by PageType. */
55
+ export function loadAnchors(dir = ANCHORS_DIR) {
56
+ const out = new Map();
57
+ if (!fs.existsSync(dir))
58
+ return out;
59
+ for (const file of fs.readdirSync(dir)) {
60
+ if (!file.endsWith('.yaml') && !file.endsWith('.yml'))
61
+ continue;
62
+ const anchor = parseAnchorFile(path.join(dir, file));
63
+ out.set(anchor.type, anchor);
64
+ }
65
+ return out;
66
+ }
67
+ /** Render an anchor as a markdown block for prompt injection. */
68
+ export function renderAnchor(anchor) {
69
+ const band = (label, b) => `${label}\n${b.criteria.map((c) => `- ${c}`).join('\n')}\nReferences: ${b.fixtures.join(', ')}`;
70
+ return [
71
+ `Calibration anchor for ${anchor.type}:`,
72
+ band('Score 9-10:', anchor.score_9_10),
73
+ band('Score 7-8:', anchor.score_7_8),
74
+ band('Score 5-6:', anchor.score_5_6),
75
+ band('Score 3-4:', anchor.score_3_4),
76
+ ].join('\n\n');
77
+ }
78
+ /**
79
+ * Minimal YAML parser scoped to the anchor file shape. Supports:
80
+ * key: scalar
81
+ * key:
82
+ * subkey: scalar
83
+ * subkey:
84
+ * - list item
85
+ *
86
+ * Indentation is normalized to spaces; tabs are not supported.
87
+ */
88
+ function parseAnchorYaml(text) {
89
+ const lines = text.split('\n').map((l) => l.replace(/\r$/, ''));
90
+ const root = {};
91
+ let i = 0;
92
+ while (i < lines.length) {
93
+ const line = lines[i];
94
+ if (!line.trim() || line.trim().startsWith('#')) {
95
+ i++;
96
+ continue;
97
+ }
98
+ const indent = leadingSpaces(line);
99
+ if (indent !== 0) {
100
+ i++;
101
+ continue;
102
+ }
103
+ const m = line.match(/^([a-zA-Z_][\w-]*):\s*(.*)$/);
104
+ if (!m) {
105
+ i++;
106
+ continue;
107
+ }
108
+ const [, key, valueRaw] = m;
109
+ const value = valueRaw.trim();
110
+ if (value === '') {
111
+ const { node, nextIndex } = readBlock(lines, i + 1, 2);
112
+ root[key] = node;
113
+ i = nextIndex;
114
+ }
115
+ else {
116
+ root[key] = parseScalar(value);
117
+ i++;
118
+ }
119
+ }
120
+ return root;
121
+ }
122
+ function readBlock(lines, startIndex, baseIndent) {
123
+ // Detect: is this a list ("- item") or a map?
124
+ let i = startIndex;
125
+ while (i < lines.length && !lines[i].trim())
126
+ i++;
127
+ if (i >= lines.length)
128
+ return { node: {}, nextIndex: i };
129
+ const firstIndent = leadingSpaces(lines[i]);
130
+ if (firstIndent < baseIndent)
131
+ return { node: {}, nextIndex: i };
132
+ if (lines[i].trim().startsWith('- ') || lines[i].trim() === '-') {
133
+ const items = [];
134
+ while (i < lines.length) {
135
+ const line = lines[i];
136
+ if (!line.trim()) {
137
+ i++;
138
+ continue;
139
+ }
140
+ const indent = leadingSpaces(line);
141
+ if (indent < baseIndent)
142
+ break;
143
+ const trimmed = line.trim();
144
+ if (!trimmed.startsWith('-'))
145
+ break;
146
+ const item = trimmed.replace(/^-\s*/, '');
147
+ items.push(parseScalar(item));
148
+ i++;
149
+ }
150
+ return { node: items, nextIndex: i };
151
+ }
152
+ const map = {};
153
+ while (i < lines.length) {
154
+ const line = lines[i];
155
+ if (!line.trim() || line.trim().startsWith('#')) {
156
+ i++;
157
+ continue;
158
+ }
159
+ const indent = leadingSpaces(line);
160
+ if (indent < baseIndent)
161
+ break;
162
+ if (indent > baseIndent) {
163
+ i++;
164
+ continue;
165
+ }
166
+ const m = line.match(/^\s*([a-zA-Z_][\w-]*):\s*(.*)$/);
167
+ if (!m) {
168
+ i++;
169
+ continue;
170
+ }
171
+ const [, key, valueRaw] = m;
172
+ const value = valueRaw.trim();
173
+ if (value === '') {
174
+ const { node, nextIndex } = readBlock(lines, i + 1, baseIndent + 2);
175
+ map[key] = node;
176
+ i = nextIndex;
177
+ }
178
+ else {
179
+ map[key] = parseScalar(value);
180
+ i++;
181
+ }
182
+ }
183
+ return { node: map, nextIndex: i };
184
+ }
185
+ function leadingSpaces(line) {
186
+ let n = 0;
187
+ while (n < line.length && line[n] === ' ')
188
+ n++;
189
+ return n;
190
+ }
191
+ function parseScalar(raw) {
192
+ let value = raw.trim();
193
+ if (value === '')
194
+ return '';
195
+ if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))) {
196
+ value = value.slice(1, -1);
197
+ }
198
+ if (value === 'true')
199
+ return true;
200
+ if (value === 'false')
201
+ return false;
202
+ if (value === 'null' || value === '~')
203
+ return null;
204
+ if (/^-?\d+$/.test(value))
205
+ return Number(value);
206
+ if (/^-?\d+\.\d+$/.test(value))
207
+ return Number(value);
208
+ return value;
209
+ }
210
+ //# sourceMappingURL=anchor-loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anchor-loader.js","sourceRoot":"","sources":["../../../../src/design/audit/rubric/anchor-loader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ type: blog
2
+ score_9_10:
3
+ criteria:
4
+ - Reading column tuned to 60-75 character measure with deliberate vertical rhythm
5
+ - Typography scale supports headings, body, callouts, code, captions distinctly
6
+ - Author identity and publication date prominent without being chrome
7
+ - Inline media (images, code, embeds) integrate cleanly with text flow
8
+ - Navigation between posts (next, related, archive) supports the reading habit
9
+ fixtures:
10
+ - fixture:stratechery
11
+ - fixture:substack-post
12
+ - fixture:notion-blog-template
13
+ score_7_8:
14
+ criteria:
15
+ - Strong reading experience but typographic scale is one step shy of intentional
16
+ - Author and date present but visually inconsistent
17
+ - Inline media works but breaks rhythm at boundaries
18
+ fixtures:
19
+ - fixture:medium-default
20
+ score_5_6:
21
+ criteria:
22
+ - Default theme typography (no custom scale, line-height defaults)
23
+ - Heavy chrome (sidebar, social rail) competing with the article
24
+ - Author/date hidden in footer
25
+ fixtures:
26
+ - fixture:default-ghost
27
+ score_3_4:
28
+ criteria:
29
+ - Article copy crammed against gutters; no measure control
30
+ - Inline ads break reading flow every paragraph
31
+ - No publication date — content is unanchored in time
32
+ fixtures:
33
+ - fixture:ad-heavy-article
@@ -0,0 +1,35 @@
1
+ type: dashboard
2
+ score_9_10:
3
+ criteria:
4
+ - Real metrics with units, time windows, and comparison baselines visible at first glance
5
+ - Charts use deliberate scales, axis labels, and selective color (not rainbow defaults)
6
+ - Filters, time ranges, and segment selectors are obvious and persistent
7
+ - Empty states preview real data shape (sample rows, last-7-days skeleton)
8
+ - Density tuned to operator workflow — no decorative whitespace where dense data belongs
9
+ fixtures:
10
+ - fixture:linear-app
11
+ - fixture:figma-file-ui
12
+ - fixture:datadog-dashboard
13
+ - fixture:vercel-dashboard
14
+ score_7_8:
15
+ criteria:
16
+ - Metrics present and useful but lack comparison baselines or time-window controls
17
+ - Charts readable but use default color palette; minor density issues
18
+ - Filters present but discoverability unclear
19
+ fixtures:
20
+ - fixture:grafana-default
21
+ score_5_6:
22
+ criteria:
23
+ - Generic stat cards (4 equal boxes) without context or comparison
24
+ - Charts are rainbow defaults from the component library
25
+ - No filters or time-range affordance
26
+ - Empty states are illustrations + platitudes
27
+ fixtures:
28
+ - fixture:generic-dashboard
29
+ score_3_4:
30
+ criteria:
31
+ - Numbers without units, labels, or context — operator cannot tell good from bad
32
+ - Decorative chart visualizations (donuts, gauges) instead of operational data
33
+ - Equal-weight UI controls; no clear workflow path
34
+ fixtures:
35
+ - fixture:empty-state-noise
@@ -0,0 +1,35 @@
1
+ type: docs
2
+ score_9_10:
3
+ criteria:
4
+ - Quickstart path from landing to a working result is obvious within one viewport
5
+ - Code samples are runnable, copy-button-equipped, and language-tabbed where relevant
6
+ - Reference structure (sidebar, breadcrumbs, search) supports both linear and lookup reading
7
+ - Versioning, deprecation, and last-updated signals are visible
8
+ - Typography scale and line-length tuned for sustained reading
9
+ fixtures:
10
+ - fixture:stripe-docs
11
+ - fixture:tailwind-docs
12
+ - fixture:mdn-docs
13
+ - fixture:vercel-docs
14
+ score_7_8:
15
+ criteria:
16
+ - Quickstart present but buried; copy is solid but examples are partial
17
+ - Sidebar IA works but search is weak or missing
18
+ - Versioning unclear
19
+ fixtures:
20
+ - fixture:generic-mkdocs
21
+ score_5_6:
22
+ criteria:
23
+ - Wall-of-text reference with no quickstart
24
+ - Code samples without copy buttons or language switching
25
+ - No search, no breadcrumbs, no last-updated metadata
26
+ - Default theme typography (inconsistent line-height, no scale)
27
+ fixtures:
28
+ - fixture:default-docusaurus
29
+ score_3_4:
30
+ criteria:
31
+ - Marketing page disguised as docs (heavy hero, no actual reference)
32
+ - No code samples or syntax highlighting
33
+ - IA broken — "Getting Started" buried under marketing copy
34
+ fixtures:
35
+ - fixture:marketing-as-docs
@@ -0,0 +1,33 @@
1
+ type: ecommerce
2
+ score_9_10:
3
+ criteria:
4
+ - Product photography is real, detailed, and honest (not stock or AI-rendered)
5
+ - Price, fees, taxes, shipping, and total are surfaced before the commit button
6
+ - Stock, delivery, and return-policy signals are visible at decision points
7
+ - Cart and checkout flows preserve context — user always knows what they are buying
8
+ - Trust signals (verified payment, secure checkout, real merchant identity) appear where commitment occurs
9
+ fixtures:
10
+ - fixture:apple-store
11
+ - fixture:shopify-storefront
12
+ - fixture:allbirds-pdp
13
+ score_7_8:
14
+ criteria:
15
+ - Solid PDPs but checkout exposes fees only at the last step
16
+ - Stock and delivery info present but inconsistent across pages
17
+ - Photography mixes real and stock
18
+ fixtures:
19
+ - fixture:generic-shopify
20
+ score_5_6:
21
+ criteria:
22
+ - Fees surfaced only after pressing Pay; no shipping calculator
23
+ - Stock/delivery signals missing on PDPs
24
+ - Generic merchant identity, no trust badges, no return policy summary
25
+ fixtures:
26
+ - fixture:hidden-fees-checkout
27
+ score_3_4:
28
+ criteria:
29
+ - Total never shown until after commitment
30
+ - No merchant identity, no return policy, no trust signals
31
+ - Forced account creation before checkout, dark-pattern upsells
32
+ fixtures:
33
+ - fixture:dark-pattern-checkout
@@ -0,0 +1,34 @@
1
+ type: marketing
2
+ score_9_10:
3
+ criteria:
4
+ - Hero answers product, audience, and outcome within five seconds
5
+ - One dominant CTA, secondary actions clearly subordinate
6
+ - Concrete proof (real customer logos, real metrics, real screenshots) above the fold
7
+ - Visual craft (typography ramp, spacing rhythm, color system) is intentional, not template-default
8
+ - Differentiation is shown, not asserted; copy avoids vague hype
9
+ fixtures:
10
+ - fixture:stripe-marketing
11
+ - fixture:linear-marketing
12
+ - fixture:vercel-marketing
13
+ - fixture:apple-marketing
14
+ score_7_8:
15
+ criteria:
16
+ - Hero clear, but proof is generic (lorem-style logo cloud) or differentiation thin
17
+ - Visual system coherent but unremarkable; one or two minor rhythm breaks
18
+ - CTA dominant on hero but competes elsewhere
19
+ fixtures:
20
+ - fixture:generic-saas-marketing
21
+ score_5_6:
22
+ criteria:
23
+ - Hero copy explains the product instead of selling the outcome
24
+ - Visual hierarchy works but feels like a Tailwind starter
25
+ - Equal-weight CTAs, vague social proof, stock illustrations
26
+ fixtures:
27
+ - fixture:meta-copy-feature
28
+ score_3_4:
29
+ criteria:
30
+ - No primary message; could swap nouns and apply to any startup
31
+ - No CTA hierarchy; the page is a wall of equal sections
32
+ - Stock photography, generic gradients, default UI kit components
33
+ fixtures:
34
+ - fixture:ambiguous-deploy