@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,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
@@ -0,0 +1,38 @@
1
+ type: saas-app
2
+ score_9_10:
3
+ criteria:
4
+ - Domain object visible above the fold (tasks, deployments, conversations, files)
5
+ - One visually-dominant primary action per page state
6
+ - Empty states preview real product (sample rows, setup checklists, status timelines), not generic illustrations
7
+ - Action hierarchy = product hierarchy; no decorative buttons competing with workflow
8
+ - Trust details visible where commitment exists (price, permissions, undo, audit trail)
9
+ fixtures:
10
+ - fixture:linear-app
11
+ - fixture:figma-file-ui
12
+ - fixture:notion-editor
13
+ - fixture:superhuman
14
+ - fixture:github-pr-view
15
+ score_7_8:
16
+ criteria:
17
+ - Most criteria from 9-10 with one or two minor gaps
18
+ - Polish gaps that don't block job completion
19
+ - Domain objects present but action hierarchy slightly diffuse
20
+ fixtures:
21
+ - fixture:airtable-grid
22
+ - fixture:notion-database
23
+ score_5_6:
24
+ criteria:
25
+ - Functional but generic component-library assembly
26
+ - No domain object above the fold OR action hierarchy unclear
27
+ - Empty states show illustrations + platitudes instead of product preview
28
+ - Multiple equal-weight CTAs without a dominant primary
29
+ fixtures:
30
+ - fixture:generic-dashboard
31
+ score_3_4:
32
+ criteria:
33
+ - No primary job inferable from screen
34
+ - Equal-weight CTAs blocking workflow
35
+ - Decorative elements actively distract from product surface
36
+ - Page reads as a marketing/setup stub rather than an operational product
37
+ fixtures:
38
+ - fixture:no-primary-action
@@ -0,0 +1,33 @@
1
+ type: social
2
+ score_9_10:
3
+ criteria:
4
+ - Feed prioritizes real content (posts, conversations) over chrome and ads
5
+ - Compose surface is one click away and primary in the layout
6
+ - Identity signals (verified accounts, profile preview, follower counts) consistent and lightweight
7
+ - State transitions (like, reply, repost) feel instant and reversible
8
+ - Empty states preview what the feed will look like with a few followed accounts
9
+ fixtures:
10
+ - fixture:threads-web
11
+ - fixture:bluesky-web
12
+ - fixture:substack-inline
13
+ score_7_8:
14
+ criteria:
15
+ - Solid feed and compose flow but reply chains are visually flat
16
+ - Identity signals inconsistent across surfaces
17
+ - Empty states use illustrations rather than previewing real content
18
+ fixtures:
19
+ - fixture:generic-microblog
20
+ score_5_6:
21
+ criteria:
22
+ - Feed cluttered with chrome (rails, ads, suggestions) competing with content
23
+ - Compose buried two clicks deep
24
+ - Action affordances (reply, like, share) are equal weight with no clear primary
25
+ fixtures:
26
+ - fixture:cluttered-feed
27
+ score_3_4:
28
+ criteria:
29
+ - Page reads as ad inventory with content squeezed in
30
+ - No clear primary feed; multiple surfaces compete
31
+ - Identity signals fake or absent (anonymous content with no provenance)
32
+ fixtures:
33
+ - fixture:ad-heavy-feed
@@ -0,0 +1,33 @@
1
+ type: tool
2
+ score_9_10:
3
+ criteria:
4
+ - Single-purpose surface — the input and output relationship is immediate and obvious
5
+ - Keyboard-first interaction (shortcuts, focus management, paste support)
6
+ - Output is copyable, exportable, and shareable without modal interruption
7
+ - Recent results, history, or undo always available
8
+ - State (input, processing, output, error) handled explicitly with clear transitions
9
+ fixtures:
10
+ - fixture:linear-command-palette
11
+ - fixture:github-pr-view
12
+ - fixture:raycast
13
+ score_7_8:
14
+ criteria:
15
+ - Tool works well but lacks keyboard affordances or history
16
+ - Output exportable but with extra clicks
17
+ - Error states present but generic
18
+ fixtures:
19
+ - fixture:generic-converter
20
+ score_5_6:
21
+ criteria:
22
+ - Form-and-submit pattern with reload-style output
23
+ - No keyboard shortcuts, no history, no undo
24
+ - Loading and error states use defaults
25
+ fixtures:
26
+ - fixture:basic-tool-form
27
+ score_3_4:
28
+ criteria:
29
+ - Multi-step flow for what should be a single action
30
+ - Output requires manual selection/copy
31
+ - No error handling — failures show generic browser errors
32
+ fixtures:
33
+ - fixture:broken-tool
@@ -0,0 +1,33 @@
1
+ type: utility
2
+ score_9_10:
3
+ criteria:
4
+ - Status, configuration, or admin surface that exposes the operational object directly (deploy, build, job, account)
5
+ - Real state (running, succeeded, failed, queued) with timestamps and durations
6
+ - Action affordances (retry, rollback, configure, audit) match the operational verbs of the system
7
+ - Logs, diagnostics, or detail panels are one click from the summary
8
+ - Empty states preview what real activity will look like
9
+ fixtures:
10
+ - fixture:vercel-deployment-status
11
+ - fixture:cloudflare-dashboard
12
+ - fixture:github-actions
13
+ score_7_8:
14
+ criteria:
15
+ - Status surface clear but action affordances are generic (Edit/Save instead of Retry/Rollback)
16
+ - Logs accessible but require navigation
17
+ - Empty states use illustrations rather than previewing activity
18
+ fixtures:
19
+ - fixture:generic-admin
20
+ score_5_6:
21
+ criteria:
22
+ - Status indicators are decorative pills without timestamps or durations
23
+ - Logs and diagnostics buried in modals
24
+ - Forms-of-forms pattern instead of operational verbs
25
+ fixtures:
26
+ - fixture:basic-settings-page
27
+ score_3_4:
28
+ criteria:
29
+ - Status is text only — no visual signal of failure or success
30
+ - No way to retry, rollback, or audit from the surface
31
+ - Settings sprawl with no IA, no search
32
+ fixtures:
33
+ - fixture:settings-sprawl
@@ -0,0 +1,42 @@
1
+ ---
2
+ id: audience-clinician
3
+ title: Clinician Audience
4
+ weight: high
5
+ applies-when:
6
+ audience: [clinician]
7
+ ---
8
+
9
+ This surface is used by clinical professionals (physicians, nurses, pharmacists,
10
+ therapists) in high-stakes decision-making contexts. Standard consumer-UX
11
+ heuristics are insufficient — apply the following additional lens.
12
+
13
+ INFORMATION DENSITY
14
+ - Clinicians tolerate and often require high information density. Sparse
15
+ consumer-style layouts that hide detail behind progressive disclosure are
16
+ friction, not polish.
17
+ - Data tables, lab result grids, medication lists must be fully visible without
18
+ expand/collapse. If key data is folded, score `content_ia` lower.
19
+
20
+ WORKFLOW EFFICIENCY
21
+ - Clinicians context-switch constantly (patient to patient, chart to EHR to
22
+ order entry). Keyboard navigation, dense primary actions, and minimal
23
+ confirmation dialogs for routine operations are expected.
24
+ - If standard consumer patterns (fat CTAs, step-by-step wizards) dominate
25
+ routine tasks, score `workflow` lower.
26
+
27
+ CRITICAL VALUE FLAGGING
28
+ - Out-of-range lab values, drug interactions, and alert states must be
29
+ immediately visible with high visual contrast — not just color. Include
30
+ icon + text pattern redundancy.
31
+ - Missing or weak critical-value flagging is a major finding in `trust_clarity`.
32
+
33
+ AUDIT TRAIL AND ATTRIBUTION
34
+ - Clinician workflows require visible "who did what, when" — last modified by,
35
+ order placed by, cosigned by. This is both regulatory and practical.
36
+ - If attributable actions lack visible provenance, that is a major finding in
37
+ `trust_clarity`.
38
+
39
+ DO NOT penalize for:
40
+ - Dense information layouts (this is intentional)
41
+ - Lack of illustrations or hero imagery
42
+ - Technical terminology appropriate to the audience
@@ -0,0 +1,40 @@
1
+ ---
2
+ id: audience-developer
3
+ title: Developer Audience
4
+ weight: medium
5
+ applies-when:
6
+ audience: [developer]
7
+ ---
8
+
9
+ This surface is used by software engineers and technical practitioners.
10
+
11
+ INFORMATION OVER DECORATION
12
+ - Code samples, CLI commands, API endpoints, and technical specifications must
13
+ be immediately accessible — not gated behind tabs, scrolling, or "Request
14
+ Demo" flows. If core technical content requires navigation to find, score
15
+ `content_ia` lower.
16
+
17
+ COPY-PASTE HYGIENE
18
+ - Every code block must have a visible copy button or be selectable without
19
+ capturing surrounding prose. Missing copy affordance is a minor-to-major
20
+ finding in `workflow` depending on frequency.
21
+
22
+ DARK MODE AND TERMINAL AESTHETICS
23
+ - Developers default to dark environments. A light-only surface with no dark
24
+ mode is a `visual_craft` minor finding. A surface that actively breaks
25
+ (illegible code contrast) in dark mode is major.
26
+
27
+ AUTHENTICATION PATHS
28
+ - API keys, tokens, and credentials should be displayed with
29
+ mask-by-default + reveal-on-click. Showing credentials in plaintext by
30
+ default is a critical `trust_clarity` finding.
31
+
32
+ SEARCH AS PRIMARY NAVIGATION
33
+ - Technical docs and reference surfaces must have a prominent, keyboard-
34
+ accessible search. If Cmd/Ctrl-K does not open search, that is a major
35
+ finding in `workflow`.
36
+
37
+ DO NOT penalize for:
38
+ - Dense information layouts
39
+ - Monospace typography sections
40
+ - Minimal illustration or marketing copy
@@ -0,0 +1,35 @@
1
+ ---
2
+ id: audience-kids
3
+ title: Kids Audience
4
+ weight: critical
5
+ applies-when:
6
+ audience: [kids]
7
+ ---
8
+
9
+ This surface is used by or targeted at minors. Apply the following additional
10
+ lens. Note: ethics rules in Layer 7 enforce hard score floors independently
11
+ of rubric scoring — both layers apply simultaneously.
12
+
13
+ AGE-APPROPRIATE LANGUAGE AND IMAGERY
14
+ - Copy must be readable at the stated age level. Technical jargon, legalese,
15
+ or implicit social pressure ("Your friends are waiting!") are major findings
16
+ in `content_ia`.
17
+ - Imagery should be appropriate for the age group. Mature themes, even subtle
18
+ ones, are critical findings in `trust_clarity`.
19
+
20
+ FRICTION-SYMMETRIC FLOWS
21
+ - Actions that benefit the operator (in-app purchase, data sharing, account
22
+ creation) must have equal or greater friction than their reversal
23
+ (cancellation, data deletion, account closure).
24
+ - Any flow where it is easier to spend money / share data than to undo is a
25
+ critical finding in `workflow`.
26
+
27
+ PARENTAL CONTROLS VISIBILITY
28
+ - If the app collects data from minors, parental consent or control mechanisms
29
+ must be visible without buried navigation. If absent: major finding in
30
+ `trust_clarity`.
31
+
32
+ DO NOT penalize for:
33
+ - Simplified language and larger touch targets
34
+ - Reduced information density appropriate to age
35
+ - Bright color palettes and playful illustration styles