cbrowser 18.78.0 → 18.80.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 (235) hide show
  1. package/dist/analysis/accessibility-empathy.d.ts.map +1 -1
  2. package/dist/analysis/accessibility-empathy.js +395 -66
  3. package/dist/analysis/accessibility-empathy.js.map +1 -1
  4. package/dist/analysis/agent-ready-audit.d.ts.map +1 -1
  5. package/dist/analysis/agent-ready-audit.js +78 -0
  6. package/dist/analysis/agent-ready-audit.js.map +1 -1
  7. package/dist/analysis/page-understanding.d.ts +139 -1
  8. package/dist/analysis/page-understanding.d.ts.map +1 -1
  9. package/dist/analysis/page-understanding.js +179 -12
  10. package/dist/analysis/page-understanding.js.map +1 -1
  11. package/dist/artifact-store.d.ts +19 -5
  12. package/dist/artifact-store.d.ts.map +1 -1
  13. package/dist/artifact-store.js +41 -11
  14. package/dist/artifact-store.js.map +1 -1
  15. package/dist/browser.d.ts +9 -0
  16. package/dist/browser.d.ts.map +1 -1
  17. package/dist/browser.js +81 -5
  18. package/dist/browser.js.map +1 -1
  19. package/dist/cli.js +55 -10
  20. package/dist/cli.js.map +1 -1
  21. package/dist/cognitive/index.d.ts.map +1 -1
  22. package/dist/cognitive/index.js +3 -2
  23. package/dist/cognitive/index.js.map +1 -1
  24. package/dist/config.d.ts +57 -0
  25. package/dist/config.d.ts.map +1 -1
  26. package/dist/config.js +234 -7
  27. package/dist/config.js.map +1 -1
  28. package/dist/index.js +1 -1
  29. package/dist/index.js.map +1 -1
  30. package/dist/mcp-server-remote.d.ts.map +1 -1
  31. package/dist/mcp-server-remote.js +108 -4
  32. package/dist/mcp-server-remote.js.map +1 -1
  33. package/dist/mcp-server.d.ts.map +1 -1
  34. package/dist/mcp-server.js +62 -938
  35. package/dist/mcp-server.js.map +1 -1
  36. package/dist/mcp-tools/account-personas.d.ts +41 -0
  37. package/dist/mcp-tools/account-personas.d.ts.map +1 -0
  38. package/dist/mcp-tools/account-personas.js +98 -0
  39. package/dist/mcp-tools/account-personas.js.map +1 -0
  40. package/dist/mcp-tools/base/analysis-tools.d.ts.map +1 -1
  41. package/dist/mcp-tools/base/analysis-tools.js +12 -2
  42. package/dist/mcp-tools/base/analysis-tools.js.map +1 -1
  43. package/dist/mcp-tools/base/artifact-tools.d.ts +3 -0
  44. package/dist/mcp-tools/base/artifact-tools.d.ts.map +1 -0
  45. package/dist/mcp-tools/base/artifact-tools.js +78 -0
  46. package/dist/mcp-tools/base/artifact-tools.js.map +1 -0
  47. package/dist/mcp-tools/base/audit-tools.d.ts +11 -0
  48. package/dist/mcp-tools/base/audit-tools.d.ts.map +1 -1
  49. package/dist/mcp-tools/base/audit-tools.js +595 -340
  50. package/dist/mcp-tools/base/audit-tools.js.map +1 -1
  51. package/dist/mcp-tools/base/browser-management-tools.d.ts.map +1 -1
  52. package/dist/mcp-tools/base/browser-management-tools.js +18 -0
  53. package/dist/mcp-tools/base/browser-management-tools.js.map +1 -1
  54. package/dist/mcp-tools/base/bug-analysis-tools.d.ts.map +1 -1
  55. package/dist/mcp-tools/base/bug-analysis-tools.js +59 -3
  56. package/dist/mcp-tools/base/bug-analysis-tools.js.map +1 -1
  57. package/dist/mcp-tools/base/capture-tools.d.ts +37 -0
  58. package/dist/mcp-tools/base/capture-tools.d.ts.map +1 -1
  59. package/dist/mcp-tools/base/capture-tools.js +267 -6
  60. package/dist/mcp-tools/base/capture-tools.js.map +1 -1
  61. package/dist/mcp-tools/base/cognitive-tools.d.ts +12 -0
  62. package/dist/mcp-tools/base/cognitive-tools.d.ts.map +1 -1
  63. package/dist/mcp-tools/base/cognitive-tools.js +63 -15
  64. package/dist/mcp-tools/base/cognitive-tools.js.map +1 -1
  65. package/dist/mcp-tools/base/extraction-tools.d.ts.map +1 -1
  66. package/dist/mcp-tools/base/extraction-tools.js +33 -2
  67. package/dist/mcp-tools/base/extraction-tools.js.map +1 -1
  68. package/dist/mcp-tools/base/index.d.ts +2 -0
  69. package/dist/mcp-tools/base/index.d.ts.map +1 -1
  70. package/dist/mcp-tools/base/index.js +9 -0
  71. package/dist/mcp-tools/base/index.js.map +1 -1
  72. package/dist/mcp-tools/base/marketing-tools.js +3 -3
  73. package/dist/mcp-tools/base/marketing-tools.js.map +1 -1
  74. package/dist/mcp-tools/base/persona-comparison-tools.d.ts.map +1 -1
  75. package/dist/mcp-tools/base/persona-comparison-tools.js +529 -40
  76. package/dist/mcp-tools/base/persona-comparison-tools.js.map +1 -1
  77. package/dist/mcp-tools/base/site-knowledge-tools.d.ts.map +1 -1
  78. package/dist/mcp-tools/base/site-knowledge-tools.js +36 -3
  79. package/dist/mcp-tools/base/site-knowledge-tools.js.map +1 -1
  80. package/dist/mcp-tools/base/values-tools.d.ts +113 -0
  81. package/dist/mcp-tools/base/values-tools.d.ts.map +1 -1
  82. package/dist/mcp-tools/base/values-tools.js +868 -78
  83. package/dist/mcp-tools/base/values-tools.js.map +1 -1
  84. package/dist/mcp-tools/base/visual-testing-tools.d.ts.map +1 -1
  85. package/dist/mcp-tools/base/visual-testing-tools.js +130 -10
  86. package/dist/mcp-tools/base/visual-testing-tools.js.map +1 -1
  87. package/dist/mcp-tools/index.d.ts +3 -1
  88. package/dist/mcp-tools/index.d.ts.map +1 -1
  89. package/dist/mcp-tools/index.js +3 -28
  90. package/dist/mcp-tools/index.js.map +1 -1
  91. package/dist/mcp-tools/persona-creation-tools.d.ts.map +1 -1
  92. package/dist/mcp-tools/persona-creation-tools.js +363 -20
  93. package/dist/mcp-tools/persona-creation-tools.js.map +1 -1
  94. package/dist/mcp-tools/persona-lifecycle-tools.d.ts +3 -0
  95. package/dist/mcp-tools/persona-lifecycle-tools.d.ts.map +1 -0
  96. package/dist/mcp-tools/persona-lifecycle-tools.js +406 -0
  97. package/dist/mcp-tools/persona-lifecycle-tools.js.map +1 -0
  98. package/dist/mcp-tools/screenshot-utils.d.ts.map +1 -1
  99. package/dist/mcp-tools/screenshot-utils.js +56 -10
  100. package/dist/mcp-tools/screenshot-utils.js.map +1 -1
  101. package/dist/mcp-tools/tier-gate.js +2 -2
  102. package/dist/mcp-tools/tier-gate.js.map +1 -1
  103. package/dist/mcp-tools/tool-categories.d.ts.map +1 -1
  104. package/dist/mcp-tools/tool-categories.js +4 -1
  105. package/dist/mcp-tools/tool-categories.js.map +1 -1
  106. package/dist/mcp-tools/ui-resources.d.ts +167 -0
  107. package/dist/mcp-tools/ui-resources.d.ts.map +1 -0
  108. package/dist/mcp-tools/ui-resources.js +707 -0
  109. package/dist/mcp-tools/ui-resources.js.map +1 -0
  110. package/dist/mcp-tools/widget-kit.d.ts +299 -0
  111. package/dist/mcp-tools/widget-kit.d.ts.map +1 -0
  112. package/dist/mcp-tools/widget-kit.js +2034 -0
  113. package/dist/mcp-tools/widget-kit.js.map +1 -0
  114. package/dist/mcp-ui-resources.d.ts.map +1 -1
  115. package/dist/mcp-ui-resources.js +14 -4
  116. package/dist/mcp-ui-resources.js.map +1 -1
  117. package/dist/persona-questionnaire.d.ts +69 -1
  118. package/dist/persona-questionnaire.d.ts.map +1 -1
  119. package/dist/persona-questionnaire.js +177 -76
  120. package/dist/persona-questionnaire.js.map +1 -1
  121. package/dist/persona-scope.d.ts +20 -0
  122. package/dist/persona-scope.d.ts.map +1 -0
  123. package/dist/persona-scope.js +59 -0
  124. package/dist/persona-scope.js.map +1 -0
  125. package/dist/personas.d.ts +51 -17
  126. package/dist/personas.d.ts.map +1 -1
  127. package/dist/personas.js +947 -286
  128. package/dist/personas.js.map +1 -1
  129. package/dist/recording/capture-player.d.ts +68 -0
  130. package/dist/recording/capture-player.d.ts.map +1 -0
  131. package/dist/recording/capture-player.js +298 -0
  132. package/dist/recording/capture-player.js.map +1 -0
  133. package/dist/recording/engine.d.ts +52 -0
  134. package/dist/recording/engine.d.ts.map +1 -1
  135. package/dist/recording/engine.js +241 -3
  136. package/dist/recording/engine.js.map +1 -1
  137. package/dist/recording/inline-player.d.ts +39 -0
  138. package/dist/recording/inline-player.d.ts.map +1 -0
  139. package/dist/recording/inline-player.js +272 -0
  140. package/dist/recording/inline-player.js.map +1 -0
  141. package/dist/recording/saliency-overlay.d.ts +133 -0
  142. package/dist/recording/saliency-overlay.d.ts.map +1 -0
  143. package/dist/recording/saliency-overlay.js +360 -0
  144. package/dist/recording/saliency-overlay.js.map +1 -0
  145. package/dist/recording/types.d.ts +32 -0
  146. package/dist/recording/types.d.ts.map +1 -1
  147. package/dist/recording/types.js +46 -0
  148. package/dist/recording/types.js.map +1 -1
  149. package/dist/site-model/manager.d.ts +20 -0
  150. package/dist/site-model/manager.d.ts.map +1 -1
  151. package/dist/site-model/manager.js +52 -0
  152. package/dist/site-model/manager.js.map +1 -1
  153. package/dist/trait-reference.d.ts +26 -2
  154. package/dist/trait-reference.d.ts.map +1 -1
  155. package/dist/trait-reference.js +129 -19
  156. package/dist/trait-reference.js.map +1 -1
  157. package/dist/types.d.ts +105 -18
  158. package/dist/types.d.ts.map +1 -1
  159. package/dist/types.js.map +1 -1
  160. package/dist/url-resolution.d.ts +58 -0
  161. package/dist/url-resolution.d.ts.map +1 -0
  162. package/dist/url-resolution.js +143 -0
  163. package/dist/url-resolution.js.map +1 -0
  164. package/dist/values/big-five-inference.d.ts +121 -0
  165. package/dist/values/big-five-inference.d.ts.map +1 -0
  166. package/dist/values/big-five-inference.js +241 -0
  167. package/dist/values/big-five-inference.js.map +1 -0
  168. package/dist/values/big-five-values.d.ts +76 -0
  169. package/dist/values/big-five-values.d.ts.map +1 -0
  170. package/dist/values/big-five-values.js +152 -0
  171. package/dist/values/big-five-values.js.map +1 -0
  172. package/dist/values/index.d.ts +1 -1
  173. package/dist/values/index.d.ts.map +1 -1
  174. package/dist/values/index.js +1 -1
  175. package/dist/values/index.js.map +1 -1
  176. package/dist/values/persona-completeness.d.ts +91 -0
  177. package/dist/values/persona-completeness.d.ts.map +1 -0
  178. package/dist/values/persona-completeness.js +114 -0
  179. package/dist/values/persona-completeness.js.map +1 -0
  180. package/dist/values/persona-diff.d.ts +50 -0
  181. package/dist/values/persona-diff.d.ts.map +1 -0
  182. package/dist/values/persona-diff.js +126 -0
  183. package/dist/values/persona-diff.js.map +1 -0
  184. package/dist/values/persona-values.d.ts +16 -0
  185. package/dist/values/persona-values.d.ts.map +1 -1
  186. package/dist/values/persona-values.js +33 -0
  187. package/dist/values/persona-values.js.map +1 -1
  188. package/dist/values/schwartz-values.d.ts +9 -1
  189. package/dist/values/schwartz-values.d.ts.map +1 -1
  190. package/dist/values/schwartz-values.js +10 -2
  191. package/dist/values/schwartz-values.js.map +1 -1
  192. package/dist/values/value-mappings.d.ts +41 -2
  193. package/dist/values/value-mappings.d.ts.map +1 -1
  194. package/dist/values/value-mappings.js +65 -8
  195. package/dist/values/value-mappings.js.map +1 -1
  196. package/dist/visual/attention-quality.d.ts +27 -0
  197. package/dist/visual/attention-quality.d.ts.map +1 -1
  198. package/dist/visual/attention-quality.js +164 -2
  199. package/dist/visual/attention-quality.js.map +1 -1
  200. package/dist/visual/attention-transport.d.ts +41 -2
  201. package/dist/visual/attention-transport.d.ts.map +1 -1
  202. package/dist/visual/attention-transport.js +98 -26
  203. package/dist/visual/attention-transport.js.map +1 -1
  204. package/dist/visual/barrier-overlay-html.d.ts +10 -0
  205. package/dist/visual/barrier-overlay-html.d.ts.map +1 -1
  206. package/dist/visual/barrier-overlay-html.js.map +1 -1
  207. package/dist/visual/cognitive-models.d.ts +109 -13
  208. package/dist/visual/cognitive-models.d.ts.map +1 -1
  209. package/dist/visual/cognitive-models.js +166 -3
  210. package/dist/visual/cognitive-models.js.map +1 -1
  211. package/dist/visual/cognitive-transport-chain.d.ts +149 -5
  212. package/dist/visual/cognitive-transport-chain.d.ts.map +1 -1
  213. package/dist/visual/cognitive-transport-chain.js +558 -30
  214. package/dist/visual/cognitive-transport-chain.js.map +1 -1
  215. package/dist/visual/cognitive-transport.d.ts +45 -3
  216. package/dist/visual/cognitive-transport.d.ts.map +1 -1
  217. package/dist/visual/cognitive-transport.js +126 -12
  218. package/dist/visual/cognitive-transport.js.map +1 -1
  219. package/dist/visual/fixation-corpus.d.ts +52 -0
  220. package/dist/visual/fixation-corpus.d.ts.map +1 -1
  221. package/dist/visual/fixation-corpus.js +95 -0
  222. package/dist/visual/fixation-corpus.js.map +1 -1
  223. package/dist/visual/llm-relevance.d.ts +193 -0
  224. package/dist/visual/llm-relevance.d.ts.map +1 -0
  225. package/dist/visual/llm-relevance.js +480 -0
  226. package/dist/visual/llm-relevance.js.map +1 -0
  227. package/dist/visual/perceptual-transport.d.ts +60 -0
  228. package/dist/visual/perceptual-transport.d.ts.map +1 -1
  229. package/dist/visual/perceptual-transport.js +228 -19
  230. package/dist/visual/perceptual-transport.js.map +1 -1
  231. package/dist/visual/persona-context.d.ts +23 -0
  232. package/dist/visual/persona-context.d.ts.map +1 -0
  233. package/dist/visual/persona-context.js +44 -0
  234. package/dist/visual/persona-context.js.map +1 -0
  235. package/package.json +2 -1
@@ -0,0 +1,298 @@
1
+ /**
2
+ * Self-contained HTML player for a capture.
3
+ *
4
+ * A recording produces a GIF, a per-keyframe attention judgement, and a closing
5
+ * narrative. None of that survives an MCP response: video cannot cross the
6
+ * boundary, and a wall of JSON is not something a person reads. This builds one
7
+ * HTML file that carries all of it, gets written to the served artifact
8
+ * directory, and comes back as a URL — so a chat client, a teammate, or a
9
+ * bookmark all resolve to the same thing.
10
+ *
11
+ * SELF-CONTAINED BY CONSTRUCTION. Everything inlines: no CDN, no stylesheet, no
12
+ * script tag pointing anywhere. The artifact directory is served as static files
13
+ * with no build step, and a player that needs a network fetch to render is a
14
+ * player that breaks the first time something upstream moves.
15
+ *
16
+ * The media itself is referenced by URL rather than inlined — a base64 WebM in
17
+ * an HTML file is a multi-megabyte document that no browser enjoys, and both
18
+ * live in the same served directory anyway.
19
+ *
20
+ * @copyright 2026 Alexandria Eden alexandria.shai.eden@gmail.com https://cbrowser.ai
21
+ * @license MIT
22
+ */
23
+ /** Escape for text nodes and quoted attributes. */
24
+ function esc(s) {
25
+ return s
26
+ .replace(/&/g, "&")
27
+ .replace(/</g, "&lt;")
28
+ .replace(/>/g, "&gt;")
29
+ .replace(/"/g, "&quot;")
30
+ .replace(/'/g, "&#39;");
31
+ }
32
+ function fmtTime(ms) {
33
+ const s = ms / 1000;
34
+ return s < 10 ? `${s.toFixed(1)}s` : `${Math.round(s)}s`;
35
+ }
36
+ /**
37
+ * Build the player document.
38
+ *
39
+ * Returns a complete HTML string; the caller writes it wherever it is served
40
+ * from. Pure, so it is testable without a filesystem or a network.
41
+ */
42
+ export function buildCapturePlayer(data) {
43
+ const video = data.artifactUrls.webm ?? data.artifactUrls.mp4;
44
+ const image = data.artifactUrls.gif ?? data.artifactUrls.webp;
45
+ const poster = data.contactSheetUrl;
46
+ // Speed control only exists for video. A GIF's frame delays are baked into the
47
+ // file and no browser API changes them, so offering a slider that silently did
48
+ // nothing would be worse than saying which artifact supports it.
49
+ const speedBar = video
50
+ ? `<div class="speed" role="group" aria-label="Playback speed">
51
+ <span class="lbl">Speed</span>
52
+ ${[0.25, 0.5, 1, 2].map((r) => `<button type="button" data-rate="${r}"${r === 1 ? ' aria-pressed="true"' : ' aria-pressed="false"'}>${r}&times;</button>`).join("")}
53
+ <button type="button" data-step="-1" title="Previous frame">&#9666;</button>
54
+ <button type="button" data-step="1" title="Next frame">&#9656;</button>
55
+ </div>`
56
+ : image
57
+ ? `<p class="speednote">Speed control needs the video artifact &mdash; capture with <code>format: "gif,webm"</code> to get it.</p>`
58
+ : "";
59
+ const media = video
60
+ ? `<video id="rec" controls loop muted playsinline${poster ? ` poster="${esc(poster)}"` : ""} src="${esc(video)}"></video>`
61
+ : image
62
+ ? `<img src="${esc(image)}" alt="Recording of ${esc(data.targetUrl ?? data.slug)}">`
63
+ : `<p class="empty">No playable artifact was produced for this capture.</p>`;
64
+ const acts = (data.interactions ?? []).slice().sort((a, b) => a.atMs - b.atMs);
65
+ const dur = Math.max(1, data.durationMs);
66
+ // Markers are positioned by fraction of capture duration, so the track lines up
67
+ // with the media above it regardless of artifact format. Only the video can be
68
+ // seeked -- for a GIF the markers still read as a record of what happened, they
69
+ // just do not drive playback, and the note says so rather than silently no-op.
70
+ const actTrack = acts.length === 0
71
+ ? ""
72
+ : `
73
+ <section class="acts">
74
+ <h2>Interactions</h2>
75
+ <p class="lede">${acts.length} recorded ${acts.length === 1 ? "event" : "events"}${video ? " &mdash; select one to jump there." : " &mdash; seeking needs the video artifact."}</p>
76
+ <div class="track" role="list">
77
+ ${acts.map((a) => `<button type="button" role="listitem" class="mark" data-at="${a.atMs}" style="--x:${((a.atMs / dur) * 100).toFixed(2)}%" title="${esc(a.type)} &middot; ${esc(a.label.slice(0, 60))}"><span class="dot" data-type="${esc(a.type)}"></span></button>`).join("")}
78
+ </div>
79
+ <ol class="actlist">
80
+ ${acts.map((a) => `<li><button type="button" data-at="${a.atMs}"><span class="t">${esc(fmtTime(a.atMs))}</span><span class="kind" data-type="${esc(a.type)}">${esc(a.type)}</span><span class="lab">${esc(a.label.slice(0, 90) || "(no label)")}</span></button></li>`).join("")}
81
+ </ol>
82
+ </section>`;
83
+ const moments = data.moments ?? [];
84
+ const timeline = moments.length === 0
85
+ ? ""
86
+ : `
87
+ <section>
88
+ <h2>Attention timeline</h2>
89
+ <p class="lede">Judged at each point the interface changed enough to re-evaluate, not on every frame.</p>
90
+ <ol class="moments">
91
+ ${moments.map((m) => `
92
+ <li>
93
+ <div class="t">${esc(fmtTime(m.tMs))}<span class="frame">frame ${m.frameIndex}</span></div>
94
+ <div class="body">
95
+ ${m.topElements.length > 0 ? `<ul class="els">${m.topElements.map((e) => `
96
+ <li><span class="bar" style="--w:${Math.round(e.score * 100)}%"></span><span class="score">${e.score.toFixed(2)}</span><span class="txt">${esc(e.text.slice(0, 80))}</span><span class="type">${esc(e.type)}</span></li>`).join("")}</ul>` : `<p class="empty">Nothing scored at this moment.</p>`}
97
+ ${m.reasoning ? `<p class="why">${esc(m.reasoning)}</p>` : ""}
98
+ </div>
99
+ </li>`).join("")}
100
+ </ol>
101
+ </section>`;
102
+ const summary = data.summary
103
+ ? `<section class="summary"><h2>How this went</h2><p>${esc(data.summary)}</p></section>`
104
+ : "";
105
+ const quantityNote = data.overlay
106
+ ? data.overlay.quantity === "predicted-attention"
107
+ ? `<span class="pill ok">predicted attention &middot; ${data.overlay.domElements} elements</span>`
108
+ : `<span class="pill warn">visual contrast only &middot; no DOM</span>`
109
+ : "";
110
+ const downloads = Object.entries(data.artifactUrls)
111
+ .map(([fmt, url]) => `<a href="${esc(url)}" download>${esc(fmt)}</a>`)
112
+ .join("");
113
+ return `<!doctype html>
114
+ <html lang="en">
115
+ <head>
116
+ <meta charset="utf-8">
117
+ <meta name="viewport" content="width=device-width,initial-scale=1">
118
+ <title>${esc(data.targetUrl ?? data.slug)} — capture</title>
119
+ <style>
120
+ :root{
121
+ --ink:#12151c; --paper:#f5f6f8; --card:#fff; --rule:#dfe3ea; --muted:#5f6874;
122
+ --accent:#2f4374; --hot:#b3252b; --ok:#2f6b4f; --warn:#8a6314;
123
+ --mono:ui-monospace,"SF Mono","Cascadia Mono",Menlo,Consolas,monospace;
124
+ }
125
+ @media(prefers-color-scheme:dark){:root{
126
+ --ink:#e6e9ef; --paper:#13161d; --card:#1a1e27; --rule:#2c333f; --muted:#98a2b2;
127
+ --accent:#95a9d8; --hot:#e4838a; --ok:#86c4a2; --warn:#d9b25f;
128
+ }}
129
+ *{box-sizing:border-box}
130
+ body{margin:0;background:var(--paper);color:var(--ink);
131
+ font:16px/1.6 "Charter","Iowan Old Style",Palatino,Georgia,serif;-webkit-font-smoothing:antialiased}
132
+ .wrap{max-width:78ch;margin:0 auto;padding:clamp(1.5rem,4vw,3rem) clamp(1rem,4vw,2rem) 5rem;
133
+ display:flex;flex-direction:column;gap:2rem}
134
+ header{display:flex;flex-direction:column;gap:.6rem}
135
+ .eyebrow{font-family:var(--mono);font-size:.7rem;letter-spacing:.13em;text-transform:uppercase;color:var(--accent)}
136
+ h1{margin:0;font-size:clamp(1.4rem,3.5vw,2rem);line-height:1.2;text-wrap:balance;word-break:break-word}
137
+ h2{font-size:1.2rem;margin:0 0 .5rem;padding-bottom:.35rem;border-bottom:1px solid var(--rule)}
138
+ .meta{display:flex;flex-wrap:wrap;gap:.4rem .9rem;font-family:var(--mono);font-size:.74rem;color:var(--muted)}
139
+ .pill{font-family:var(--mono);font-size:.66rem;letter-spacing:.05em;text-transform:uppercase;
140
+ padding:.18rem .5rem;border-radius:100px;white-space:nowrap}
141
+ .pill.ok{background:color-mix(in srgb,var(--ok) 16%,transparent);color:var(--ok)}
142
+ .pill.warn{background:color-mix(in srgb,var(--warn) 18%,transparent);color:var(--warn)}
143
+ figure{margin:0;background:var(--card);border:1px solid var(--rule);border-radius:6px;overflow:hidden}
144
+ video,img{display:block;width:100%;height:auto;background:#000}
145
+ .lede{color:var(--muted);margin:.2rem 0 1rem;font-size:.95rem}
146
+ .speed{display:flex;align-items:center;gap:.4rem;flex-wrap:wrap;margin-top:-1.4rem}
147
+ .speed .lbl{font-family:var(--mono);font-size:.68rem;letter-spacing:.1em;text-transform:uppercase;color:var(--muted);margin-right:.2rem}
148
+ .speed button{font-family:var(--mono);font-size:.76rem;padding:.28rem .6rem;border:1px solid var(--rule);
149
+ border-radius:3px;background:var(--card);color:var(--ink);cursor:pointer}
150
+ .speed button:hover{border-color:var(--accent)}
151
+ .speed button[aria-pressed="true"]{background:var(--accent);color:var(--card);border-color:var(--accent)}
152
+ .speed button:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
153
+ .speednote{font-size:.85rem;color:var(--muted);margin-top:-1.4rem}
154
+ .acts .lede{margin-bottom:.5rem}
155
+ .acts .track{position:relative;height:26px;margin:.2rem 0 .9rem;border-radius:4px;
156
+ background:linear-gradient(90deg,color-mix(in srgb,var(--rule) 55%,transparent),color-mix(in srgb,var(--rule) 20%,transparent));
157
+ border:1px solid var(--rule)}
158
+ .acts .mark{position:absolute;left:var(--x);top:0;height:100%;width:18px;transform:translateX(-9px);
159
+ background:none;border:0;padding:0;cursor:pointer;display:grid;place-items:center}
160
+ .acts .mark .dot{width:11px;height:11px;border-radius:50%;background:var(--accent);
161
+ border:2px solid var(--card);box-shadow:0 0 0 1px var(--accent)}
162
+ .acts .mark .dot[data-type="submit"]{background:#d1495b;box-shadow:0 0 0 1px #d1495b}
163
+ .acts .mark .dot[data-type="input"]{background:#e0a458;box-shadow:0 0 0 1px #e0a458}
164
+ .acts .mark:hover .dot{transform:scale(1.35)}
165
+ .acts .mark:focus-visible{outline:2px solid var(--accent);outline-offset:1px;border-radius:3px}
166
+ .actlist{list-style:none;padding:0;margin:0;display:flex;flex-direction:column;gap:.15rem}
167
+ .actlist button{display:flex;gap:.6rem;align-items:baseline;width:100%;text-align:left;
168
+ background:none;border:0;border-radius:4px;padding:.3rem .45rem;cursor:pointer;color:inherit;font:inherit}
169
+ .actlist button:hover{background:color-mix(in srgb,var(--accent) 9%,transparent)}
170
+ .actlist button:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}
171
+ .actlist .t{font-family:var(--mono);font-size:.74rem;color:var(--muted);flex:0 0 3.6rem;font-variant-numeric:tabular-nums}
172
+ .actlist .kind{font-family:var(--mono);font-size:.66rem;text-transform:uppercase;letter-spacing:.08em;
173
+ padding:.08rem .34rem;border-radius:3px;background:color-mix(in srgb,var(--accent) 16%,transparent);flex:0 0 auto}
174
+ .actlist .kind[data-type="submit"]{background:color-mix(in srgb,#d1495b 18%,transparent)}
175
+ .actlist .kind[data-type="input"]{background:color-mix(in srgb,#e0a458 22%,transparent)}
176
+ .actlist .lab{font-size:.85rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
177
+ @media (prefers-reduced-motion:reduce){.acts .mark:hover .dot{transform:none}}
178
+ .moments{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:.9rem}
179
+ .moments>li{display:grid;grid-template-columns:5.5rem 1fr;gap:0 1rem;background:var(--card);
180
+ border:1px solid var(--rule);border-left:3px solid var(--accent);border-radius:4px;padding:.9rem 1rem}
181
+ .t{font-family:var(--mono);font-size:.9rem;font-weight:600;font-variant-numeric:tabular-nums;
182
+ display:flex;flex-direction:column;gap:.15rem}
183
+ .frame{font-weight:400;font-size:.66rem;color:var(--muted)}
184
+ .els{list-style:none;margin:0 0 .5rem;padding:0;display:flex;flex-direction:column;gap:.3rem}
185
+ .els li{display:grid;grid-template-columns:7rem 2.6rem 1fr auto;align-items:center;gap:.5rem;font-size:.86rem}
186
+ /* Track + fill, so a 0.44 reads as visibly under half rather than as a short
187
+ bar the eye has nothing to compare against. */
188
+ .els li>span:first-child{position:relative;height:.5rem;border-radius:2px;
189
+ background:color-mix(in srgb,var(--rule) 70%,transparent)}
190
+ .bar::after{content:"";position:absolute;inset:0 auto 0 0;width:var(--w);
191
+ border-radius:2px;background:linear-gradient(90deg,var(--accent),var(--hot))}
192
+ .score{font-family:var(--mono);font-size:.76rem;font-variant-numeric:tabular-nums;color:var(--muted)}
193
+ .txt{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
194
+ .type{font-family:var(--mono);font-size:.64rem;text-transform:uppercase;color:var(--muted)}
195
+ .why{margin:.4rem 0 0;font-size:.92rem;color:var(--ink)}
196
+ .summary{background:var(--card);border:1px solid var(--rule);border-left:3px solid var(--ok);
197
+ border-radius:4px;padding:1.1rem 1.3rem}
198
+ .summary p{margin:0}
199
+ .empty{color:var(--muted);font-style:italic;margin:0}
200
+ .dl{display:flex;gap:.5rem;flex-wrap:wrap}
201
+ .dl a{font-family:var(--mono);font-size:.72rem;text-transform:uppercase;letter-spacing:.05em;
202
+ padding:.3rem .7rem;border:1px solid var(--rule);border-radius:3px;color:var(--accent);text-decoration:none}
203
+ .dl a:hover,.dl a:focus-visible{border-color:var(--accent)}
204
+ footer{border-top:1px solid var(--rule);padding-top:1rem;font-size:.8rem;color:var(--muted)}
205
+ a:focus-visible,video:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
206
+ @media(prefers-reduced-motion:reduce){*{animation:none!important;transition:none!important}}
207
+ @media(max-width:600px){.moments>li{grid-template-columns:1fr;gap:.5rem}
208
+ .els li{grid-template-columns:5rem 2.4rem 1fr;}.type{display:none}}
209
+ </style>
210
+ </head>
211
+ <body>
212
+ <div class="wrap">
213
+ <header>
214
+ <div class="eyebrow">cbrowser capture</div>
215
+ <h1>${esc(data.targetUrl ?? data.slug)}</h1>
216
+ <div class="meta">
217
+ <span>${esc(fmtTime(data.durationMs))}</span>
218
+ <span>${data.frames} frames</span>
219
+ <span>${data.actualFps.toFixed(1)} fps</span>
220
+ ${data.personaName ? `<span>persona: ${esc(data.personaName)}</span>` : ""}
221
+ ${data.goal ? `<span>goal: ${esc(data.goal)}</span>` : ""}
222
+ ${quantityNote}
223
+ </div>
224
+ </header>
225
+
226
+ <figure>${media}</figure>
227
+ ${speedBar}
228
+ ${actTrack}
229
+
230
+ ${summary}
231
+ ${timeline}
232
+
233
+ ${downloads ? `<section><h2>Files</h2><div class="dl">${downloads}</div></section>` : ""}
234
+
235
+ <footer>
236
+ ${data.overlay
237
+ ? data.overlay.quantity === "predicted-attention"
238
+ ? "Overlay shows the model&rsquo;s predicted attention, blending visual contrast with DOM semantics. It has not been validated against human eye movements."
239
+ : "Overlay shows visual contrast only &mdash; no DOM was available, so the semantic half of the model did not run."
240
+ : "No attention overlay was applied to this capture."}
241
+ </footer>
242
+ </div>
243
+ <script>
244
+ // Interaction seeking lives in its own IIFE: the player script below returns
245
+ // early when there is no <video>, and the markers must still render and respond
246
+ // on a GIF-only capture even though nothing can be seeked.
247
+ (function () {
248
+ var v = document.getElementById("rec");
249
+ document.querySelectorAll("[data-at]").forEach(function (b) {
250
+ b.addEventListener("click", function () {
251
+ var t = parseInt(b.getAttribute("data-at"), 10) / 1000;
252
+ if (v && isFinite(t)) { v.currentTime = t; v.pause(); }
253
+ document.querySelectorAll("[data-at]").forEach(function (o) {
254
+ o.setAttribute("aria-current", o === b ? "true" : "false");
255
+ });
256
+ });
257
+ });
258
+ })();
259
+ (function () {
260
+ var v = document.getElementById("rec");
261
+ if (!v) return;
262
+ var bar = document.querySelector(".speed");
263
+ if (!bar) return;
264
+
265
+ // Frame step uses the capture's real rate, not a guessed 30fps — stepping by
266
+ // the wrong interval lands between frames and looks like nothing happened.
267
+ var FRAME = ${data.actualFps > 0 ? (1 / data.actualFps).toFixed(4) : "0.25"};
268
+
269
+ bar.addEventListener("click", function (e) {
270
+ var b = e.target.closest("button");
271
+ if (!b) return;
272
+ if (b.dataset.rate) {
273
+ v.playbackRate = parseFloat(b.dataset.rate);
274
+ bar.querySelectorAll("[data-rate]").forEach(function (o) {
275
+ o.setAttribute("aria-pressed", String(o === b));
276
+ });
277
+ return;
278
+ }
279
+ if (b.dataset.step) {
280
+ v.pause();
281
+ v.currentTime = Math.max(0, v.currentTime + parseInt(b.dataset.step, 10) * FRAME);
282
+ }
283
+ });
284
+
285
+ document.addEventListener("keydown", function (e) {
286
+ if (e.target && /input|textarea/i.test(e.target.tagName)) return;
287
+ if (e.key === "," || e.key === ".") {
288
+ e.preventDefault();
289
+ v.pause();
290
+ v.currentTime = Math.max(0, v.currentTime + (e.key === "." ? FRAME : -FRAME));
291
+ }
292
+ });
293
+ })();
294
+ </script>
295
+ </body>
296
+ </html>`;
297
+ }
298
+ //# sourceMappingURL=capture-player.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capture-player.js","sourceRoot":"","sources":["../../src/recording/capture-player.ts"],"names":[],"mappings":"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"}
@@ -50,6 +50,24 @@ export interface VideoCaptureOptions {
50
50
  columns?: number;
51
51
  maxFrames?: number;
52
52
  };
53
+ /**
54
+ * Paint the visual-contrast (saliency) map over every frame before encoding.
55
+ *
56
+ * Opt-in because it costs one saliency pass per frame (~0.5-1s each), so a
57
+ * 50-frame capture adds 30-60s. The result is a CONTRAST map, not a gaze
58
+ * prediction — see `saliency-overlay.ts` for why that distinction is load-bearing.
59
+ */
60
+ saliencyOverlay?: boolean | {
61
+ opacity?: number;
62
+ floor?: number;
63
+ cellSize?: number;
64
+ /** Persona whose priorities weight the semantic half of the blend. */
65
+ persona?: string;
66
+ /** Goal string weighting goal-relevance in the semantic half. */
67
+ goal?: string;
68
+ /** Whether the caller may spend paid model calls on judging and summary. */
69
+ entitled?: boolean;
70
+ };
53
71
  /** Delay the first frame until this condition holds. */
54
72
  startTrigger?: StartTrigger;
55
73
  /** Extra delay after the start trigger fires, in milliseconds. */
@@ -109,6 +127,40 @@ export declare class VideoCaptureSession {
109
127
  private startedAtIso;
110
128
  private stopWallMs;
111
129
  private frames;
130
+ /**
131
+ * DOM as it stood at a point in time, captured on navigation.
132
+ *
133
+ * Reading the DOM once at stop and stamping it across every frame is wrong the
134
+ * moment a capture navigates: frame 0 on the pricing page was being judged
135
+ * against the post-click verification screen, which made every judged moment
136
+ * identical and let the summary confabulate a UX finding out of a tool
137
+ * artifact. One extract per navigation is cheap; per frame would be a
138
+ * page.evaluate on every screencast tick.
139
+ */
140
+ private domSnapshots;
141
+ /**
142
+ * Scroll position over time, sampled cheaply.
143
+ *
144
+ * Element rects come from getBoundingClientRect, which is VIEWPORT-relative at
145
+ * the instant of extraction. Between snapshots the page keeps scrolling, so a
146
+ * rect captured before a scroll describes a position the element has since
147
+ * left — the heat lands below where the element now is, by exactly the drift.
148
+ * Storing scroll per sample lets the renderer correct each frame back to what
149
+ * was actually on screen.
150
+ */
151
+ private scrollTrack;
152
+ /**
153
+ * Real interactions, captured from the page rather than inferred.
154
+ *
155
+ * The capture summary previously read the gap between two scripted tool calls
156
+ * as a user deliberating, and recommended a design change to fix the stall it
157
+ * had invented. Gagging the prompt stops the bad sentence; recording what
158
+ * actually happened is what makes the good one possible — and it is the same
159
+ * data needed to draw a ring where a click landed.
160
+ */
161
+ private interactions;
162
+ private navListener?;
163
+ private scrollTimer?;
112
164
  private nextDueMs;
113
165
  private writeQueue;
114
166
  private consoleEvents;
@@ -1 +1 @@
1
- {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/recording/engine.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/recording/engine.ts"],"names":[],"mappings":"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"}