cbrowser 20.2.2 → 21.0.1

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 (311) hide show
  1. package/README.md +2 -2
  2. package/dist/analysis/accessibility-empathy.d.ts +29 -1
  3. package/dist/analysis/accessibility-empathy.d.ts.map +1 -1
  4. package/dist/analysis/accessibility-empathy.js +69 -35
  5. package/dist/analysis/accessibility-empathy.js.map +1 -1
  6. package/dist/browser.d.ts.map +1 -1
  7. package/dist/browser.js +11 -7
  8. package/dist/browser.js.map +1 -1
  9. package/dist/cif-score.d.ts +56 -5
  10. package/dist/cif-score.d.ts.map +1 -1
  11. package/dist/cif-score.js +595 -346
  12. package/dist/cif-score.js.map +1 -1
  13. package/dist/cli.js +10 -8
  14. package/dist/cli.js.map +1 -1
  15. package/dist/cognitive/default-traits.d.ts +14 -0
  16. package/dist/cognitive/default-traits.d.ts.map +1 -0
  17. package/dist/cognitive/default-traits.js +36 -0
  18. package/dist/cognitive/default-traits.js.map +1 -0
  19. package/dist/cognitive/emotions.d.ts.map +1 -1
  20. package/dist/cognitive/emotions.js +104 -174
  21. package/dist/cognitive/emotions.js.map +1 -1
  22. package/dist/cognitive/index.d.ts +28 -0
  23. package/dist/cognitive/index.d.ts.map +1 -1
  24. package/dist/cognitive/index.js +353 -287
  25. package/dist/cognitive/index.js.map +1 -1
  26. package/dist/cognitive/temporal.d.ts +0 -24
  27. package/dist/cognitive/temporal.d.ts.map +1 -1
  28. package/dist/cognitive/temporal.js +45 -35
  29. package/dist/cognitive/temporal.js.map +1 -1
  30. package/dist/data/ctc-reference-v2-2026-10-24.d.ts +16 -0
  31. package/dist/data/ctc-reference-v2-2026-10-24.d.ts.map +1 -0
  32. package/dist/data/ctc-reference-v2-2026-10-24.js +1004 -0
  33. package/dist/data/ctc-reference-v2-2026-10-24.js.map +1 -0
  34. package/dist/ideal-profiles-gap.d.ts +1 -0
  35. package/dist/ideal-profiles-gap.d.ts.map +1 -1
  36. package/dist/ideal-profiles-gap.js +9 -1
  37. package/dist/ideal-profiles-gap.js.map +1 -1
  38. package/dist/ideal-profiles.d.ts +8 -0
  39. package/dist/ideal-profiles.d.ts.map +1 -1
  40. package/dist/ideal-profiles.js +28 -24
  41. package/dist/ideal-profiles.js.map +1 -1
  42. package/dist/mcp-server-remote.d.ts.map +1 -1
  43. package/dist/mcp-server-remote.js +7 -8
  44. package/dist/mcp-server-remote.js.map +1 -1
  45. package/dist/mcp-tools/account-personas.d.ts.map +1 -1
  46. package/dist/mcp-tools/account-personas.js +3 -1
  47. package/dist/mcp-tools/account-personas.js.map +1 -1
  48. package/dist/mcp-tools/base/answer-provenance.d.ts +28 -0
  49. package/dist/mcp-tools/base/answer-provenance.d.ts.map +1 -0
  50. package/dist/mcp-tools/base/answer-provenance.js +32 -0
  51. package/dist/mcp-tools/base/answer-provenance.js.map +1 -0
  52. package/dist/mcp-tools/base/audit-tools.d.ts +0 -3
  53. package/dist/mcp-tools/base/audit-tools.d.ts.map +1 -1
  54. package/dist/mcp-tools/base/audit-tools.js +152 -84
  55. package/dist/mcp-tools/base/audit-tools.js.map +1 -1
  56. package/dist/mcp-tools/base/capture-tools.js +1 -1
  57. package/dist/mcp-tools/base/capture-tools.js.map +1 -1
  58. package/dist/mcp-tools/base/chain-values.d.ts +38 -0
  59. package/dist/mcp-tools/base/chain-values.d.ts.map +1 -0
  60. package/dist/mcp-tools/base/chain-values.js +85 -0
  61. package/dist/mcp-tools/base/chain-values.js.map +1 -0
  62. package/dist/mcp-tools/base/cognitive-tools.d.ts.map +1 -1
  63. package/dist/mcp-tools/base/cognitive-tools.js +126 -120
  64. package/dist/mcp-tools/base/cognitive-tools.js.map +1 -1
  65. package/dist/mcp-tools/base/gif-tools.d.ts.map +1 -1
  66. package/dist/mcp-tools/base/gif-tools.js +23 -5
  67. package/dist/mcp-tools/base/gif-tools.js.map +1 -1
  68. package/dist/mcp-tools/base/persona-comparison-tools.d.ts.map +1 -1
  69. package/dist/mcp-tools/base/persona-comparison-tools.js +229 -172
  70. package/dist/mcp-tools/base/persona-comparison-tools.js.map +1 -1
  71. package/dist/mcp-tools/base/site-familiarity.d.ts +31 -0
  72. package/dist/mcp-tools/base/site-familiarity.d.ts.map +1 -0
  73. package/dist/mcp-tools/base/site-familiarity.js +30 -0
  74. package/dist/mcp-tools/base/site-familiarity.js.map +1 -0
  75. package/dist/mcp-tools/base/site-knowledge-tools.js +1 -1
  76. package/dist/mcp-tools/base/site-knowledge-tools.js.map +1 -1
  77. package/dist/mcp-tools/base/story-narrative.d.ts +50 -0
  78. package/dist/mcp-tools/base/story-narrative.d.ts.map +1 -0
  79. package/dist/mcp-tools/base/story-narrative.js +88 -0
  80. package/dist/mcp-tools/base/story-narrative.js.map +1 -0
  81. package/dist/mcp-tools/base/values-tools.d.ts.map +1 -1
  82. package/dist/mcp-tools/base/values-tools.js +19 -5
  83. package/dist/mcp-tools/base/values-tools.js.map +1 -1
  84. package/dist/mcp-tools/base/visual-testing-tools.d.ts +5 -5
  85. package/dist/mcp-tools/base/visual-testing-tools.d.ts.map +1 -1
  86. package/dist/mcp-tools/base/visual-testing-tools.js +38 -11
  87. package/dist/mcp-tools/base/visual-testing-tools.js.map +1 -1
  88. package/dist/mcp-tools/persona-creation-tools.js +6 -6
  89. package/dist/mcp-tools/persona-creation-tools.js.map +1 -1
  90. package/dist/mcp-tools/persona-lifecycle-tools.d.ts.map +1 -1
  91. package/dist/mcp-tools/persona-lifecycle-tools.js +5 -1
  92. package/dist/mcp-tools/persona-lifecycle-tools.js.map +1 -1
  93. package/dist/mcp-tools/tier-gate.js +1 -1
  94. package/dist/mcp-tools/tool-result-saver.d.ts +7 -0
  95. package/dist/mcp-tools/tool-result-saver.d.ts.map +1 -1
  96. package/dist/mcp-tools/tool-result-saver.js +11 -0
  97. package/dist/mcp-tools/tool-result-saver.js.map +1 -1
  98. package/dist/mcp-tools/trait-provenance.d.ts +109 -0
  99. package/dist/mcp-tools/trait-provenance.d.ts.map +1 -0
  100. package/dist/mcp-tools/trait-provenance.js +187 -0
  101. package/dist/mcp-tools/trait-provenance.js.map +1 -0
  102. package/dist/mcp-tools/ui-resources.d.ts +6 -7
  103. package/dist/mcp-tools/ui-resources.d.ts.map +1 -1
  104. package/dist/mcp-tools/ui-resources.js +162 -12
  105. package/dist/mcp-tools/ui-resources.js.map +1 -1
  106. package/dist/mcp-tools/widget-kit.d.ts +129 -3
  107. package/dist/mcp-tools/widget-kit.d.ts.map +1 -1
  108. package/dist/mcp-tools/widget-kit.js +507 -28
  109. package/dist/mcp-tools/widget-kit.js.map +1 -1
  110. package/dist/performance/metrics.d.ts.map +1 -1
  111. package/dist/performance/metrics.js +4 -1
  112. package/dist/performance/metrics.js.map +1 -1
  113. package/dist/persona-age.d.ts +59 -0
  114. package/dist/persona-age.d.ts.map +1 -0
  115. package/dist/persona-age.js +84 -0
  116. package/dist/persona-age.js.map +1 -0
  117. package/dist/persona-questionnaire.js +1 -1
  118. package/dist/persona-questionnaire.js.map +1 -1
  119. package/dist/personas.d.ts +3 -1
  120. package/dist/personas.d.ts.map +1 -1
  121. package/dist/personas.js +154 -119
  122. package/dist/personas.js.map +1 -1
  123. package/dist/recording/engine.d.ts.map +1 -1
  124. package/dist/recording/engine.js +5 -2
  125. package/dist/recording/engine.js.map +1 -1
  126. package/dist/recording/saliency-overlay.d.ts +8 -3
  127. package/dist/recording/saliency-overlay.d.ts.map +1 -1
  128. package/dist/recording/saliency-overlay.js +14 -5
  129. package/dist/recording/saliency-overlay.js.map +1 -1
  130. package/dist/recording/types.js +1 -1
  131. package/dist/testing/nl-test-suite.d.ts.map +1 -1
  132. package/dist/testing/nl-test-suite.js +2 -1
  133. package/dist/testing/nl-test-suite.js.map +1 -1
  134. package/dist/trait-reference.d.ts +19 -2
  135. package/dist/trait-reference.d.ts.map +1 -1
  136. package/dist/trait-reference.js +19 -2
  137. package/dist/trait-reference.js.map +1 -1
  138. package/dist/types.d.ts +32 -21
  139. package/dist/types.d.ts.map +1 -1
  140. package/dist/types.js +62 -52
  141. package/dist/types.js.map +1 -1
  142. package/dist/values/persona-completeness.js +1 -1
  143. package/dist/values/persona-completeness.js.map +1 -1
  144. package/dist/visual/ab-comparison.d.ts.map +1 -1
  145. package/dist/visual/ab-comparison.js +4 -1
  146. package/dist/visual/ab-comparison.js.map +1 -1
  147. package/dist/visual/attention-quality.d.ts +1 -1
  148. package/dist/visual/attention-quality.js +1 -1
  149. package/dist/visual/attention-transport.d.ts +74 -10
  150. package/dist/visual/attention-transport.d.ts.map +1 -1
  151. package/dist/visual/attention-transport.js +353 -193
  152. package/dist/visual/attention-transport.js.map +1 -1
  153. package/dist/visual/cognitive-models.d.ts +77 -55
  154. package/dist/visual/cognitive-models.d.ts.map +1 -1
  155. package/dist/visual/cognitive-models.js +231 -104
  156. package/dist/visual/cognitive-models.js.map +1 -1
  157. package/dist/visual/cognitive-transport-chain.d.ts +328 -30
  158. package/dist/visual/cognitive-transport-chain.d.ts.map +1 -1
  159. package/dist/visual/cognitive-transport-chain.js +576 -353
  160. package/dist/visual/cognitive-transport-chain.js.map +1 -1
  161. package/dist/visual/cognitive-transport.d.ts +446 -13
  162. package/dist/visual/cognitive-transport.d.ts.map +1 -1
  163. package/dist/visual/cognitive-transport.js +1085 -245
  164. package/dist/visual/cognitive-transport.js.map +1 -1
  165. package/dist/visual/cross-browser.d.ts.map +1 -1
  166. package/dist/visual/cross-browser.js +8 -6
  167. package/dist/visual/cross-browser.js.map +1 -1
  168. package/dist/visual/ctc-bands.d.ts +91 -0
  169. package/dist/visual/ctc-bands.d.ts.map +1 -0
  170. package/dist/visual/ctc-bands.js +117 -0
  171. package/dist/visual/ctc-bands.js.map +1 -0
  172. package/dist/visual/ctc-reference.d.ts +287 -0
  173. package/dist/visual/ctc-reference.d.ts.map +1 -0
  174. package/dist/visual/ctc-reference.js +376 -0
  175. package/dist/visual/ctc-reference.js.map +1 -0
  176. package/dist/visual/demand-laws.d.ts +145 -0
  177. package/dist/visual/demand-laws.d.ts.map +1 -0
  178. package/dist/visual/demand-laws.js +220 -0
  179. package/dist/visual/demand-laws.js.map +1 -0
  180. package/dist/visual/distance-metrics.d.ts +23 -1
  181. package/dist/visual/distance-metrics.d.ts.map +1 -1
  182. package/dist/visual/distance-metrics.js +49 -18
  183. package/dist/visual/distance-metrics.js.map +1 -1
  184. package/dist/visual/dro-bound.d.ts +220 -0
  185. package/dist/visual/dro-bound.d.ts.map +1 -0
  186. package/dist/visual/dro-bound.js +341 -0
  187. package/dist/visual/dro-bound.js.map +1 -0
  188. package/dist/visual/exact-w1.d.ts +60 -0
  189. package/dist/visual/exact-w1.d.ts.map +1 -0
  190. package/dist/visual/exact-w1.js +247 -0
  191. package/dist/visual/exact-w1.js.map +1 -0
  192. package/dist/visual/human-input.d.ts.map +1 -1
  193. package/dist/visual/human-input.js +45 -41
  194. package/dist/visual/human-input.js.map +1 -1
  195. package/dist/visual/index.d.ts +2 -0
  196. package/dist/visual/index.d.ts.map +1 -1
  197. package/dist/visual/index.js +2 -0
  198. package/dist/visual/index.js.map +1 -1
  199. package/dist/visual/law-times-report.d.ts +49 -0
  200. package/dist/visual/law-times-report.d.ts.map +1 -0
  201. package/dist/visual/law-times-report.js +38 -0
  202. package/dist/visual/law-times-report.js.map +1 -0
  203. package/dist/visual/model-provenance.d.ts +151 -0
  204. package/dist/visual/model-provenance.d.ts.map +1 -0
  205. package/dist/visual/model-provenance.js +335 -0
  206. package/dist/visual/model-provenance.js.map +1 -0
  207. package/dist/visual/normal-cdf.d.ts +14 -0
  208. package/dist/visual/normal-cdf.d.ts.map +1 -0
  209. package/dist/visual/normal-cdf.js +26 -0
  210. package/dist/visual/normal-cdf.js.map +1 -0
  211. package/dist/visual/perceptual-transport.d.ts +28 -4
  212. package/dist/visual/perceptual-transport.d.ts.map +1 -1
  213. package/dist/visual/perceptual-transport.js +66 -32
  214. package/dist/visual/perceptual-transport.js.map +1 -1
  215. package/dist/visual/provenance/age.d.ts +30 -0
  216. package/dist/visual/provenance/age.d.ts.map +1 -0
  217. package/dist/visual/provenance/age.js +28 -0
  218. package/dist/visual/provenance/age.js.map +1 -0
  219. package/dist/visual/provenance/attention.d.ts +55 -0
  220. package/dist/visual/provenance/attention.d.ts.map +1 -0
  221. package/dist/visual/provenance/attention.js +188 -0
  222. package/dist/visual/provenance/attention.js.map +1 -0
  223. package/dist/visual/provenance/chain.d.ts +41 -0
  224. package/dist/visual/provenance/chain.d.ts.map +1 -0
  225. package/dist/visual/provenance/chain.js +66 -0
  226. package/dist/visual/provenance/chain.js.map +1 -0
  227. package/dist/visual/provenance/cif.d.ts +42 -0
  228. package/dist/visual/provenance/cif.d.ts.map +1 -0
  229. package/dist/visual/provenance/cif.js +116 -0
  230. package/dist/visual/provenance/cif.js.map +1 -0
  231. package/dist/visual/provenance/ctc-reference.d.ts +36 -0
  232. package/dist/visual/provenance/ctc-reference.d.ts.map +1 -0
  233. package/dist/visual/provenance/ctc-reference.js +96 -0
  234. package/dist/visual/provenance/ctc-reference.js.map +1 -0
  235. package/dist/visual/provenance/distance.d.ts +10 -0
  236. package/dist/visual/provenance/distance.d.ts.map +1 -0
  237. package/dist/visual/provenance/distance.js +72 -0
  238. package/dist/visual/provenance/distance.js.map +1 -0
  239. package/dist/visual/provenance/dro.d.ts +10 -0
  240. package/dist/visual/provenance/dro.d.ts.map +1 -0
  241. package/dist/visual/provenance/dro.js +2 -0
  242. package/dist/visual/provenance/dro.js.map +1 -0
  243. package/dist/visual/provenance/emotion.d.ts +26 -0
  244. package/dist/visual/provenance/emotion.d.ts.map +1 -0
  245. package/dist/visual/provenance/emotion.js +99 -0
  246. package/dist/visual/provenance/emotion.js.map +1 -0
  247. package/dist/visual/provenance/human-input.d.ts +19 -0
  248. package/dist/visual/provenance/human-input.d.ts.map +1 -0
  249. package/dist/visual/provenance/human-input.js +84 -0
  250. package/dist/visual/provenance/human-input.js.map +1 -0
  251. package/dist/visual/provenance/journey-group.d.ts +15 -0
  252. package/dist/visual/provenance/journey-group.d.ts.map +1 -0
  253. package/dist/visual/provenance/journey-group.js +15 -0
  254. package/dist/visual/provenance/journey-group.js.map +1 -0
  255. package/dist/visual/provenance/journey-mcp.d.ts +24 -0
  256. package/dist/visual/provenance/journey-mcp.d.ts.map +1 -0
  257. package/dist/visual/provenance/journey-mcp.js +54 -0
  258. package/dist/visual/provenance/journey-mcp.js.map +1 -0
  259. package/dist/visual/provenance/journey.d.ts +34 -0
  260. package/dist/visual/provenance/journey.d.ts.map +1 -0
  261. package/dist/visual/provenance/journey.js +184 -0
  262. package/dist/visual/provenance/journey.js.map +1 -0
  263. package/dist/visual/provenance/laws.d.ts +38 -0
  264. package/dist/visual/provenance/laws.d.ts.map +1 -0
  265. package/dist/visual/provenance/laws.js +40 -0
  266. package/dist/visual/provenance/laws.js.map +1 -0
  267. package/dist/visual/provenance/page-metrics.d.ts +42 -0
  268. package/dist/visual/provenance/page-metrics.d.ts.map +1 -0
  269. package/dist/visual/provenance/page-metrics.js +79 -0
  270. package/dist/visual/provenance/page-metrics.js.map +1 -0
  271. package/dist/visual/provenance/perceptual.d.ts +63 -0
  272. package/dist/visual/provenance/perceptual.d.ts.map +1 -0
  273. package/dist/visual/provenance/perceptual.js +115 -0
  274. package/dist/visual/provenance/perceptual.js.map +1 -0
  275. package/dist/visual/provenance/persona-rates.d.ts +84 -0
  276. package/dist/visual/provenance/persona-rates.d.ts.map +1 -0
  277. package/dist/visual/provenance/persona-rates.js +108 -0
  278. package/dist/visual/provenance/persona-rates.js.map +1 -0
  279. package/dist/visual/provenance/personas.d.ts +122 -0
  280. package/dist/visual/provenance/personas.d.ts.map +1 -0
  281. package/dist/visual/provenance/personas.js +298 -0
  282. package/dist/visual/provenance/personas.js.map +1 -0
  283. package/dist/visual/provenance/profiles.d.ts +39 -0
  284. package/dist/visual/provenance/profiles.d.ts.map +1 -0
  285. package/dist/visual/provenance/profiles.js +37 -0
  286. package/dist/visual/provenance/profiles.js.map +1 -0
  287. package/dist/visual/provenance/temporal.d.ts +21 -0
  288. package/dist/visual/provenance/temporal.d.ts.map +1 -0
  289. package/dist/visual/provenance/temporal.js +56 -0
  290. package/dist/visual/provenance/temporal.js.map +1 -0
  291. package/dist/visual/provenance/visual-distance.d.ts +22 -0
  292. package/dist/visual/provenance/visual-distance.d.ts.map +1 -0
  293. package/dist/visual/provenance/visual-distance.js +30 -0
  294. package/dist/visual/provenance/visual-distance.js.map +1 -0
  295. package/dist/visual/regression.d.ts.map +1 -1
  296. package/dist/visual/regression.js +14 -9
  297. package/dist/visual/regression.js.map +1 -1
  298. package/dist/visual/responsive.d.ts.map +1 -1
  299. package/dist/visual/responsive.js +4 -1
  300. package/dist/visual/responsive.js.map +1 -1
  301. package/dist/visual/scope-prose.js +2 -2
  302. package/dist/visual/scope-prose.js.map +1 -1
  303. package/dist/visual/seeded-random.d.ts +16 -0
  304. package/dist/visual/seeded-random.d.ts.map +1 -0
  305. package/dist/visual/seeded-random.js +25 -0
  306. package/dist/visual/seeded-random.js.map +1 -0
  307. package/dist/visual/stored-accessibility-traits.d.ts +27 -0
  308. package/dist/visual/stored-accessibility-traits.d.ts.map +1 -0
  309. package/dist/visual/stored-accessibility-traits.js +35 -0
  310. package/dist/visual/stored-accessibility-traits.js.map +1 -0
  311. package/package.json +1 -1
package/dist/personas.js CHANGED
@@ -17,10 +17,25 @@ import { AGENT_PERSONAS, isAgentPersona, getAgentPersona, listAgentPersonas, isA
17
17
  import { scopedDataDir, scopedAccountId } from "./persona-scope.js";
18
18
  import { currentRequestIdentity } from "./request-context.js";
19
19
  import { TRAIT_DEFINITIONS, canonicalizeTraits } from "./trait-reference.js";
20
+ import { customReadingRateId, customReadingRule, displayReadingWpm } from "./visual/provenance/persona-rates.js";
21
+ import { readPersonaAge, isOlderAdult } from "./persona-age.js";
22
+ import { ageValue } from "./visual/provenance/age.js";
20
23
  // ============================================================================
21
24
  // Custom Personas Storage
22
25
  // ============================================================================
23
- const DATA_DIR = process.env.CBROWSER_DATA_DIR || join(homedir(), ".cbrowser");
26
+ /**
27
+ * The unscoped data dir, read per call like the scoped one below.
28
+ *
29
+ * It was a constant read once at import. A process that never changes
30
+ * CBROWSER_DATA_DIR (the CLI, a server) sees no difference, but one that
31
+ * does kept the first value: in a `bun test` run, which shares one module
32
+ * registry across files, whichever file imported this first fixed the
33
+ * directory, and later files' temp CBROWSER_DATA_DIR were ignored, so their
34
+ * personas landed in ~/.cbrowser/personas (tests/real-personas-dir.test.ts).
35
+ */
36
+ function dataDir() {
37
+ return process.env.CBROWSER_DATA_DIR || join(homedir(), ".cbrowser");
38
+ }
24
39
  /**
25
40
  * Resolved per call, not once at module load.
26
41
  *
@@ -35,7 +50,7 @@ const DATA_DIR = process.env.CBROWSER_DATA_DIR || join(homedir(), ".cbrowser");
35
50
  * is the shape this codebase already removed from the billing path. (2026-08-01)
36
51
  */
37
52
  function personasDirFor() {
38
- return join(scopedDataDir() ?? DATA_DIR, "personas");
53
+ return join(scopedDataDir() ?? dataDir(), "personas");
39
54
  }
40
55
  // ============================================================================
41
56
  // Runtime Persona Registry (for Enterprise extensions)
@@ -76,8 +91,9 @@ function scopedAccountPersonas() {
76
91
  return id === undefined ? {} : ACCOUNT_PERSONAS.get(id) ?? {};
77
92
  }
78
93
  function ensurePersonasDir() {
79
- if (!existsSync(DATA_DIR)) {
80
- mkdirSync(DATA_DIR, { recursive: true });
94
+ const base = dataDir();
95
+ if (!existsSync(base)) {
96
+ mkdirSync(base, { recursive: true });
81
97
  }
82
98
  if (!existsSync(personasDirFor())) {
83
99
  mkdirSync(personasDirFor(), { recursive: true });
@@ -331,7 +347,9 @@ export function listInvalidPersonas() {
331
347
  * Generate a persona from a natural language description using AI.
332
348
  * This creates realistic behavioral parameters based on the description.
333
349
  */
334
- export function generatePersonaFromDescription(name, description) {
350
+ export function generatePersonaFromDescription(name, description,
351
+ /** An age range the author set (e.g. "65-74", "30"); wins over the description. */
352
+ statedAgeRange) {
335
353
  // Analyze description for key traits
336
354
  const descLower = description.toLowerCase();
337
355
  // Determine tech level
@@ -339,7 +357,7 @@ export function generatePersonaFromDescription(name, description) {
339
357
  if (descLower.match(/expert|developer|engineer|tech.?savvy|power user|advanced/)) {
340
358
  techLevel = "expert";
341
359
  }
342
- else if (descLower.match(/beginner|new|first.?time|elderly|senior|novice|learning/)) {
360
+ else if (descLower.match(/beginner|new|first.?time|novice|learning/)) {
343
361
  techLevel = "beginner";
344
362
  }
345
363
  // Determine device
@@ -350,20 +368,13 @@ export function generatePersonaFromDescription(name, description) {
350
368
  else if (descLower.match(/tablet|ipad/)) {
351
369
  device = "tablet";
352
370
  }
353
- // Determine age range
354
- let ageRange = "25-45";
355
- if (descLower.match(/elderly|senior|older|65\+|retired/)) {
356
- ageRange = "65+";
357
- }
358
- else if (descLower.match(/teen|young|student|gen.?z|18-24/)) {
359
- ageRange = "18-24";
360
- }
361
- else if (descLower.match(/middle.?age|40s|50s/)) {
362
- ageRange = "45-65";
363
- }
371
+ // Age: only what the author stated (src/persona-age.ts). "Senior",
372
+ // "older" and "retired" alone state no age.
373
+ const ageRange = readPersonaAge({ name, description, ageRange: statedAgeRange }).label;
374
+ const olderAdult = isOlderAdult({ name, description, ageRange: statedAgeRange });
364
375
  // Determine speed/patience traits
365
376
  const isImpatient = descLower.match(/impatient|rush|fast|quick|busy|frustrated|annoyed/);
366
- const isSlow = descLower.match(/slow|careful|cautious|elderly|senior|deliberate|thorough/);
377
+ const isSlow = descLower.match(/slow|careful|cautious|deliberate|thorough/);
367
378
  const isDistracted = descLower.match(/distract|adhd|multitask|busy|interrupt/);
368
379
  // Determine disability/accessibility needs
369
380
  const hasVisionIssues = descLower.match(/vision|blind|visually.?impaired|screen.?reader|low.?vision/);
@@ -372,7 +383,11 @@ export function generatePersonaFromDescription(name, description) {
372
383
  let reactionMin = 200, reactionMax = 500;
373
384
  let clickDelayMin = 100, clickDelayMax = 300;
374
385
  let typeSpeedMin = 50, typeSpeedMax = 120;
375
- let readingSpeed = 250;
386
+ // 238 wpm (Brysbaert 2019) x the custom-persona reading rule's share: the
387
+ // reference unless the description names dyslexia, low vision or old age
388
+ // (provenance/persona-rates.ts). Replaced keyword guesses of 400 / 250 / 150 /
389
+ // 100 wpm that no source gave.
390
+ const readingSpeed = displayReadingWpm(customReadingRateId(customReadingRule({ name, description })));
376
391
  let scrollPauseMin = 200, scrollPauseMax = 500;
377
392
  if (techLevel === "expert" || isImpatient) {
378
393
  reactionMin = 100;
@@ -381,7 +396,6 @@ export function generatePersonaFromDescription(name, description) {
381
396
  clickDelayMax = 150;
382
397
  typeSpeedMin = 30;
383
398
  typeSpeedMax = 80;
384
- readingSpeed = 400;
385
399
  scrollPauseMin = 100;
386
400
  scrollPauseMax = 300;
387
401
  }
@@ -392,18 +406,16 @@ export function generatePersonaFromDescription(name, description) {
392
406
  clickDelayMax = 800;
393
407
  typeSpeedMin = 100;
394
408
  typeSpeedMax = 200;
395
- readingSpeed = 150;
396
409
  scrollPauseMin = 500;
397
410
  scrollPauseMax = 1500;
398
411
  }
399
- if (hasMotorIssues || ageRange === "65+") {
412
+ if (hasMotorIssues || olderAdult) {
400
413
  reactionMin = Math.max(reactionMin, 800);
401
414
  reactionMax = Math.max(reactionMax, 2000);
402
415
  clickDelayMin = Math.max(clickDelayMin, 500);
403
416
  clickDelayMax = Math.max(clickDelayMax, 1200);
404
417
  typeSpeedMin = Math.max(typeSpeedMin, 150);
405
418
  typeSpeedMax = Math.max(typeSpeedMax, 300);
406
- readingSpeed = Math.min(readingSpeed, 100);
407
419
  }
408
420
  // Calculate error parameters
409
421
  let misClickRate = 0.05;
@@ -521,7 +533,7 @@ export function generatePersonaFromDescription(name, description) {
521
533
  behaviors.short_sessions = true;
522
534
  }
523
535
  // Generate cognitive traits based on analysis
524
- const cognitiveTraits = generateCognitiveTraitsFromDescription(descLower, techLevel, isImpatient, isSlow, hasVisionIssues, ageRange);
536
+ const cognitiveTraits = generateCognitiveTraitsFromDescription(descLower, techLevel, isImpatient, isSlow, hasVisionIssues, olderAdult);
525
537
  return {
526
538
  name,
527
539
  description,
@@ -570,7 +582,7 @@ export function generatePersonaFromDescription(name, description) {
570
582
  /**
571
583
  * Generate cognitive traits from a description analysis.
572
584
  */
573
- function generateCognitiveTraitsFromDescription(descLower, techLevel, isImpatient, isSlow, hasVisionIssues, ageRange) {
585
+ function generateCognitiveTraitsFromDescription(descLower, techLevel, isImpatient, isSlow, hasVisionIssues, olderAdult) {
574
586
  // Base traits by tech level
575
587
  let patience = 0.5;
576
588
  let riskTolerance = 0.5;
@@ -616,14 +628,12 @@ function generateCognitiveTraitsFromDescription(descLower, techLevel, isImpatien
616
628
  readingTendency = Math.max(readingTendency, 0.9);
617
629
  // Careful users often have moderate resilience - methodical recovery
618
630
  }
619
- // Adjust for elderly
620
- if (ageRange === "65+") {
621
- patience = Math.max(patience, 0.9);
622
- riskTolerance = Math.min(riskTolerance, 0.15);
623
- comprehension = Math.min(comprehension, 0.25);
624
- workingMemory = Math.min(workingMemory, 0.35);
625
- readingTendency = Math.max(readingTendency, 0.85);
626
- resilience = Math.min(resilience, 0.3); // Low - frustration lingers with age
631
+ // Older age: working memory only, the one trait with a published age
632
+ // direction (provenance/age.ts). Pointing and reading slow through the
633
+ // elderly rate profiles instead. The 13 other caps this block and the one
634
+ // below set for anyone guessed 65+ had no source and are gone (21.0.1).
635
+ if (olderAdult) {
636
+ workingMemory = Math.min(workingMemory, ageValue("age.olderAdult.workingMemory"));
627
637
  }
628
638
  // Adjust for vision issues (screen reader users)
629
639
  if (hasVisionIssues) {
@@ -709,17 +719,6 @@ function generateCognitiveTraitsFromDescription(descLower, techLevel, isImpatien
709
719
  metacognitivePlanning = Math.max(metacognitivePlanning, 0.8); // Plan carefully
710
720
  fearOfMissingOut = Math.min(fearOfMissingOut, 0.2); // Not swayed by urgency
711
721
  }
712
- // Adjust for elderly
713
- if (ageRange === "65+") {
714
- informationForaging = Math.min(informationForaging, 0.3); // Exhaustive search
715
- changeBlindness = Math.max(changeBlindness, 0.7); // Miss changes
716
- anchoringBias = Math.max(anchoringBias, 0.7); // Anchored to first info
717
- attributionStyle = Math.max(attributionStyle, 0.8); // Blame self
718
- proceduralFluency = Math.min(proceduralFluency, 0.35); // Struggle with sequences
719
- transferLearning = Math.min(transferLearning, 0.25); // Each UI novel
720
- authoritySensitivity = Math.max(authoritySensitivity, 0.7); // Trust authority
721
- mentalModelFlexibility = Math.min(mentalModelFlexibility, 0.2); // Rigid mental models
722
- }
723
722
  // Adjust for vision issues (screen reader users)
724
723
  if (hasVisionIssues) {
725
724
  informationForaging = Math.max(informationForaging, 0.7); // Sequential but efficient
@@ -759,7 +758,7 @@ function generateCognitiveTraitsFromDescription(descLower, techLevel, isImpatien
759
758
  */
760
759
  export function createCognitivePersona(name, description, traits, options = {}) {
761
760
  // Start with a base persona from description
762
- const basePersona = generatePersonaFromDescription(name, description);
761
+ const basePersona = generatePersonaFromDescription(name, description, options.ageRange);
763
762
  // Merge provided traits with defaults
764
763
  const cognitiveTraits = {
765
764
  patience: traits.patience ?? basePersona.cognitiveTraits?.patience ?? 0.5,
@@ -1159,7 +1158,7 @@ export const BUILTIN_PERSONAS = {
1159
1158
  reactionTime: { min: 100, max: 300 },
1160
1159
  clickDelay: { min: 50, max: 150 },
1161
1160
  typeSpeed: { min: 30, max: 80 },
1162
- readingSpeed: 400,
1161
+ readingSpeed: displayReadingWpm("personaRate.power-user.reading"),
1163
1162
  scrollPauseTime: { min: 100, max: 300 },
1164
1163
  },
1165
1164
  errors: {
@@ -1238,7 +1237,7 @@ export const BUILTIN_PERSONAS = {
1238
1237
  reactionTime: { min: 500, max: 1500 },
1239
1238
  clickDelay: { min: 300, max: 800 },
1240
1239
  typeSpeed: { min: 100, max: 200 },
1241
- readingSpeed: 150,
1240
+ readingSpeed: displayReadingWpm("personaRate.first-timer.reading"),
1242
1241
  scrollPauseTime: { min: 500, max: 1500 },
1243
1242
  },
1244
1243
  errors: {
@@ -1261,7 +1260,7 @@ export const BUILTIN_PERSONAS = {
1261
1260
  },
1262
1261
  },
1263
1262
  cognitiveTraits: {
1264
- patience: 0.7, // Medium - willing to learn
1263
+ patience: 0.7, // High - willing to invest time learning; expects some initial friction
1265
1264
  riskTolerance: 0.3, // Low - hesitates before clicking
1266
1265
  comprehension: 0.3, // Low - doesn't know conventions
1267
1266
  persistence: 0.5, // Medium - tries a few times
@@ -1311,7 +1310,7 @@ export const BUILTIN_PERSONAS = {
1311
1310
  reactionTime: { min: 200, max: 600 },
1312
1311
  clickDelay: { min: 150, max: 400 },
1313
1312
  typeSpeed: { min: 80, max: 150 },
1314
- readingSpeed: 200,
1313
+ readingSpeed: displayReadingWpm("personaRate.mobile-user.reading"),
1315
1314
  scrollPauseTime: { min: 200, max: 500 },
1316
1315
  },
1317
1316
  errors: {
@@ -1384,7 +1383,7 @@ export const BUILTIN_PERSONAS = {
1384
1383
  reactionTime: { min: 300, max: 800 },
1385
1384
  clickDelay: { min: 200, max: 500 },
1386
1385
  typeSpeed: { min: 50, max: 120 },
1387
- readingSpeed: 250,
1386
+ readingSpeed: displayReadingWpm("personaRate.screen-reader-user.reading"),
1388
1387
  scrollPauseTime: { min: 300, max: 700 },
1389
1388
  },
1390
1389
  errors: {
@@ -1417,14 +1416,14 @@ export const BUILTIN_PERSONAS = {
1417
1416
  // Sources: Information Wayfinding of Screen Reader Users, ASSETS 2024
1418
1417
  // (dl.acm.org/doi/fullHtml/10.1145/3663548.3688539); Context-Aware
1419
1418
  // Guidance for Screen Reader Users, CHI 2026 (10.1145/3772318.3790661).
1420
- riskTolerance: 0.2, // Medium - careful but experienced
1419
+ riskTolerance: 0.2, // Low - unexpected behaviour disorients without visual context
1421
1420
  comprehension: 0.8, // High - expert at a11y patterns
1422
1421
  persistence: 0.9, // High - determination required
1423
1422
  curiosity: 0.2, // Low - structured navigation
1424
1423
  workingMemory: 0.7, // High - mental model essential
1425
1424
  readingTendency: 0.9, // Full - ALL content is read aloud
1426
1425
  resilience: 0.8, // High - experienced with setbacks (CD-RISC)
1427
- selfEfficacy: 0.7, // Medium - high in accessible sites, low otherwise (Bandura)
1426
+ selfEfficacy: 0.7, // High - confident despite environmental barriers; lower on inaccessible sites (Bandura)
1428
1427
  satisficing: 0.6, // Medium - relies on structured review content (Simon)
1429
1428
  trustCalibration: 0.6, // Medium - cautious from past a11y failures (Fogg)
1430
1429
  interruptRecovery: 0.6, // High - strong mental model aids recovery (Mark)
@@ -1434,7 +1433,7 @@ export const BUILTIN_PERSONAS = {
1434
1433
  anchoringBias: 0.4, // Medium - sequential exposure to info
1435
1434
  timeHorizon: 0.3, // Long-term - patient, thorough
1436
1435
  attributionStyle: 0.4, // Medium - blames inaccessible design
1437
- metacognitivePlanning: 0.7, // Very high - plans navigation carefully
1436
+ metacognitivePlanning: 0.7, // High - plans navigation carefully
1438
1437
  proceduralFluency: 0.8, // High - follows heading structure
1439
1438
  transferLearning: 0.7, // High - knows a11y patterns across sites
1440
1439
  authoritySensitivity: 0.5, // Medium - verifies with screen reader
@@ -1466,7 +1465,7 @@ export const BUILTIN_PERSONAS = {
1466
1465
  reactionTime: { min: 800, max: 2000 },
1467
1466
  clickDelay: { min: 500, max: 1200 },
1468
1467
  typeSpeed: { min: 150, max: 300 },
1469
- readingSpeed: 100,
1468
+ readingSpeed: displayReadingWpm("personaRate.elderly-user.reading"),
1470
1469
  scrollPauseTime: { min: 800, max: 2000 },
1471
1470
  },
1472
1471
  errors: {
@@ -1493,7 +1492,7 @@ export const BUILTIN_PERSONAS = {
1493
1492
  riskTolerance: 0.2, // Very low - afraid of mistakes
1494
1493
  comprehension: 0.2, // Low - unfamiliar with modern UI
1495
1494
  persistence: 0.6, // High - determined but confused
1496
- curiosity: 0.4, // Very low - just wants to finish
1495
+ curiosity: 0.4, // Low-medium - goal-focused, prefers familiar patterns
1497
1496
  workingMemory: 0.4, // Low - may forget steps
1498
1497
  readingTendency: 0.8, // High - reads everything carefully
1499
1498
  resilience: 0.3, // Low - frustration lingers longer (BRS age-related)
@@ -1537,7 +1536,7 @@ export const BUILTIN_PERSONAS = {
1537
1536
  // procedural schema at all.
1538
1537
  proceduralFluency: 0.5,
1539
1538
  transferLearning: 0.2, // Low - each new site is confusing
1540
- authoritySensitivity: 0.7, // Very high - trusts official-looking things
1539
+ authoritySensitivity: 0.7, // High - trusts official-looking things
1541
1540
  emotionalContagion: 0.6, // Medium-high - affected by stern warnings
1542
1541
  fearOfMissingOut: 0.3, // Low - not driven by urgency, confused by it
1543
1542
  socialProofSensitivity: 0.7, // High - relies on grandchildren's recommendations
@@ -1572,7 +1571,7 @@ export const BUILTIN_PERSONAS = {
1572
1571
  reactionTime: { min: 100, max: 400 },
1573
1572
  clickDelay: { min: 80, max: 200 },
1574
1573
  typeSpeed: { min: 40, max: 100 },
1575
- readingSpeed: 350,
1574
+ readingSpeed: displayReadingWpm("personaRate.impatient-user.reading"),
1576
1575
  scrollPauseTime: { min: 100, max: 300 },
1577
1576
  },
1578
1577
  errors: {
@@ -1599,21 +1598,21 @@ export const BUILTIN_PERSONAS = {
1599
1598
  riskTolerance: 0.6, // High - clicks first thing
1600
1599
  comprehension: 0.6, // Medium
1601
1600
  persistence: 0.2, // Very low - one strike and out
1602
- curiosity: 0.3, // Very low - no time to explore
1601
+ curiosity: 0.3, // Low - no time to explore
1603
1602
  workingMemory: 0.6, // Medium
1604
1603
  readingTendency: 0.1, // Almost none - scanning only
1605
- resilience: 0.3, // Very low - no recovery, abandons (BRS)
1604
+ resilience: 0.3, // Low - frustration escalates quickly, abandons (BRS)
1606
1605
  selfEfficacy: 0.6, // Medium - impatient doesn't mean incapable (Bandura)
1607
1606
  satisficing: 0.9, // Very high - definition of satisficing (Simon)
1608
1607
  trustCalibration: 0.7, // High - clicks through without reading (Fogg)
1609
1608
  interruptRecovery: 0.2, // Very low - abandons rather than resumes (Mark)
1610
1609
  // New traits (v15.0.0)
1611
1610
  informationForaging: 0.9, // Very high - follows first scent, moves on
1612
- changeBlindness: 0.7, // Medium - focused on task
1611
+ changeBlindness: 0.7, // High - misses changes while hunting for the CTA
1613
1612
  anchoringBias: 0.6, // Medium-high - goes with first option
1614
1613
  timeHorizon: 0.95, // Maximum short-term - no time for later
1615
1614
  attributionStyle: 0.3, // Low - blames slow site
1616
- metacognitivePlanning: 0.3, // Very low - no planning, just clicking
1615
+ metacognitivePlanning: 0.3, // Low - minimal planning, just clicking
1617
1616
  proceduralFluency: 0.6, // Medium - can follow if fast
1618
1617
  transferLearning: 0.7, // High - recognizes patterns quickly
1619
1618
  authoritySensitivity: 0.4, // Medium - only if it speeds things up
@@ -1643,7 +1642,7 @@ export const BUILTIN_PERSONAS = {
1643
1642
  humanBehavior: {
1644
1643
  timing: {
1645
1644
  reactionTime: { min: 250, max: 1400 }, clickDelay: { min: 120, max: 500 },
1646
- typeSpeed: { min: 25, max: 70 }, readingSpeed: 200,
1645
+ typeSpeed: { min: 25, max: 70 }, readingSpeed: displayReadingWpm("personaRate.distracted-user.reading"),
1647
1646
  scrollPauseTime: { min: 200, max: 1500 },
1648
1647
  },
1649
1648
  errors: { misClickRate: 0.09, doubleClickAccidental: 0.04, typoRate: 0.08, backtrackRate: 0.35 },
@@ -1671,7 +1670,7 @@ export const BUILTIN_PERSONAS = {
1671
1670
  humanBehavior: {
1672
1671
  timing: {
1673
1672
  reactionTime: { min: 600, max: 2500 }, clickDelay: { min: 300, max: 900 },
1674
- typeSpeed: { min: 30, max: 80 }, readingSpeed: 130,
1673
+ typeSpeed: { min: 30, max: 80 }, readingSpeed: displayReadingWpm("personaRate.careful-reader.reading"),
1675
1674
  scrollPauseTime: { min: 800, max: 3000 },
1676
1675
  },
1677
1676
  errors: { misClickRate: 0.02, doubleClickAccidental: 0.01, typoRate: 0.02, backtrackRate: 0.08 },
@@ -1698,7 +1697,7 @@ export const BUILTIN_PERSONAS = {
1698
1697
  humanBehavior: {
1699
1698
  timing: {
1700
1699
  reactionTime: { min: 200, max: 900 }, clickDelay: { min: 100, max: 350 },
1701
- typeSpeed: { min: 45, max: 110 }, readingSpeed: 250,
1700
+ typeSpeed: { min: 45, max: 110 }, readingSpeed: displayReadingWpm("personaRate.explorer.reading"),
1702
1701
  scrollPauseTime: { min: 200, max: 1200 },
1703
1702
  },
1704
1703
  errors: { misClickRate: 0.05, doubleClickAccidental: 0.02, typoRate: 0.04, backtrackRate: 0.25 },
@@ -1725,7 +1724,7 @@ export const BUILTIN_PERSONAS = {
1725
1724
  humanBehavior: {
1726
1725
  timing: {
1727
1726
  reactionTime: { min: 200, max: 800 }, clickDelay: { min: 100, max: 300 },
1728
- typeSpeed: { min: 40, max: 100 }, readingSpeed: 260,
1727
+ typeSpeed: { min: 40, max: 100 }, readingSpeed: displayReadingWpm("personaRate.task-focused.reading"),
1729
1728
  scrollPauseTime: { min: 150, max: 600 },
1730
1729
  },
1731
1730
  errors: { misClickRate: 0.04, doubleClickAccidental: 0.02, typoRate: 0.04, backtrackRate: 0.12 },
@@ -1819,7 +1818,7 @@ export const ACCESSIBILITY_PERSONAS = {
1819
1818
  reactionTime: { min: 600, max: 1500 },
1820
1819
  clickDelay: { min: 400, max: 1000 },
1821
1820
  typeSpeed: { min: 150, max: 300 },
1822
- readingSpeed: 200,
1821
+ readingSpeed: displayReadingWpm("personaRate.motor-impairment-tremor.reading"),
1823
1822
  scrollPauseTime: { min: 500, max: 1200 },
1824
1823
  },
1825
1824
  errors: {
@@ -1865,7 +1864,10 @@ export const ACCESSIBILITY_PERSONAS = {
1865
1864
  // Research: Motor issues make resumption harder but adaptation helps (Mark)
1866
1865
  // Re-acquiring a small target after an interruption repeats the hardest
1867
1866
  // part of the interaction.
1868
- interruptRecovery: 0.6,
1867
+ // (21.0: restored to the 0.4 this citation was written beside. The doc
1868
+ // reconciliation of 2026-08-02 had set 0.6, above neutral, which
1869
+ // contradicts the direction cited here.)
1870
+ interruptRecovery: 0.4,
1869
1871
  // Every pointing action costs time and repeat attempts, so tolerance for
1870
1872
  // slow interaction is built in -- the persona's own research note records
1871
1873
  // 1-15Hz tremor and misclicks as the primary barrier.
@@ -1924,7 +1926,7 @@ export const ACCESSIBILITY_PERSONAS = {
1924
1926
  reactionTime: { min: 400, max: 1000 },
1925
1927
  clickDelay: { min: 300, max: 700 },
1926
1928
  typeSpeed: { min: 100, max: 180 },
1927
- readingSpeed: 100, // Slower due to magnification
1929
+ readingSpeed: displayReadingWpm("personaRate.low-vision-magnified.reading"),
1928
1930
  scrollPauseTime: { min: 600, max: 1500 },
1929
1931
  },
1930
1932
  errors: {
@@ -1970,10 +1972,16 @@ export const ACCESSIBILITY_PERSONAS = {
1970
1972
  cognitiveTraits: {
1971
1973
  // Research: Visual impairment + self-efficacy (Brody et al., 2002 - AMD and depression)
1972
1974
  // Reduced vision correlates with lower confidence in task completion
1973
- selfEfficacy: 0.6,
1975
+ // (21.0: restored to the 0.45 this citation was written beside. The doc
1976
+ // reconciliation of 2026-08-02 had set 0.6, above neutral, which
1977
+ // contradicts the direction cited here.)
1978
+ selfEfficacy: 0.45,
1974
1979
  // Research: Limited information access increases satisficing (Pachur & Hertwig, 2006)
1975
1980
  // Seeing only 1/9th of screen at a time → accept accessible options
1976
- satisficing: 0.4,
1981
+ // (21.0: restored to the 0.65 this citation was written beside. The doc
1982
+ // reconciliation of 2026-08-02 had set 0.4, the maximiser side, which
1983
+ // contradicts the direction cited here.)
1984
+ satisficing: 0.65,
1977
1985
  // Research: Vision impairment increases caution (Brody 2002)
1978
1986
  trustCalibration: 0.4,
1979
1987
  // Research: Limited visible area makes context recovery harder (Mark)
@@ -1993,7 +2001,7 @@ export const ACCESSIBILITY_PERSONAS = {
1993
2001
  timeHorizon: 0.4, // Patient, knows it takes time
1994
2002
  attributionStyle: 0.5, // Balanced - knows about limitations
1995
2003
  metacognitivePlanning: 0.7, // Plans navigation with zoom
1996
- proceduralFluency: 0.6, // Harder with limited view
2004
+ proceduralFluency: 0.6, // Medium-high - builds routines for familiar sites; new layouts are harder with a limited view
1997
2005
  transferLearning: 0.6, // Standard
1998
2006
  authoritySensitivity: 0.5,
1999
2007
  emotionalContagion: 0.4,
@@ -2004,7 +2012,8 @@ export const ACCESSIBILITY_PERSONAS = {
2004
2012
  },
2005
2013
  "cognitive-adhd": {
2006
2014
  name: "cognitive-adhd",
2007
- // Research: 75-81% of ADHD cases show central executive WM impairment (PMC7483636)
2015
+ // Research: 75-81% of ADHD cases show central executive WM impairment
2016
+ // (Kofler et al. 2020, PMC7483636)
2008
2017
  // Impulsivity affects persistence and patience significantly
2009
2018
  description: "User with ADHD affecting focus and working memory",
2010
2019
  disabilityType: "Cognitive (ADHD/Attention)",
@@ -2025,7 +2034,7 @@ export const ACCESSIBILITY_PERSONAS = {
2025
2034
  reactionTime: { min: 150, max: 600 }, // Can be fast when hyperfocused
2026
2035
  clickDelay: { min: 100, max: 400 },
2027
2036
  typeSpeed: { min: 50, max: 120 },
2028
- readingSpeed: 250,
2037
+ readingSpeed: displayReadingWpm("personaRate.cognitive-adhd.reading"),
2029
2038
  scrollPauseTime: { min: 100, max: 400 },
2030
2039
  },
2031
2040
  errors: {
@@ -2088,7 +2097,17 @@ export const ACCESSIBILITY_PERSONAS = {
2088
2097
  // and "may blame self" beside 0.3 on a scale whose 1.0 end is "Blames
2089
2098
  // self". The prose was right every time; the digit was inverted.
2090
2099
  cognitiveTraits: {
2091
- workingMemory: 0.3, // Research: large magnitude impairment (d=1.63-2.03)
2100
+ // Norm-anchored (paper section 3.1.1): the percentile of the adult
2101
+ // population's mean on a normed instrument. Adults with ADHD average
2102
+ // 95.2 on the WAIS-IV Working Memory Index, 95% CI 92.5-98.0, against
2103
+ // the norm of 100 (SD 15) (Wilson 2024, Arch Clin Neuropsychol
2104
+ // 39(4):498-515, Table 5). Phi((95.2 - 100) / 15) = 0.37, interval
2105
+ // 0.31-0.45. Was 0.3, cited to Kofler et al. 2020 (Neuropsychology
2106
+ // 34(6):686-698, PMC7483636; d = 1.63-2.03), whose sample is 172
2107
+ // children aged 8-13; that study now gives the direction only.
2108
+ // Still a hypothesis: that the WMI measures this trait is our mapping.
2109
+ // research/persona-norms/applied.md.
2110
+ workingMemory: 0.37,
2092
2111
  patience: 0.2, // Impulsivity: low tolerance for waiting
2093
2112
  persistence: 0.3, // Low for unengaging tasks; can hyperfocus on interesting ones
2094
2113
  curiosity: 0.9, // High novelty-seeking
@@ -2102,7 +2121,7 @@ export const ACCESSIBILITY_PERSONAS = {
2102
2121
  // claims at face value" -- which is what impulsive clicking without
2103
2122
  // reading looks like.
2104
2123
  trustCalibration: 0.65,
2105
- interruptRecovery: 0.3, // Very low - WM deficits make recovery difficult (Mark)
2124
+ interruptRecovery: 0.3, // Low - WM deficits make recovery difficult (Mark)
2106
2125
  // New traits (v15.0.0)
2107
2126
  comprehension: 0.6, // Capable when engaged; this is UI-convention grasp, not reading
2108
2127
  informationForaging: 0.4, // Distractible; goes down tangential paths (doc; code had 0.6)
@@ -2116,7 +2135,7 @@ export const ACCESSIBILITY_PERSONAS = {
2116
2135
  // KEPT over the doc's 0.3. 1.0 is "Blames self (internal attribution)",
2117
2136
  // and the doc's own rationale for 0.3 was "may blame self".
2118
2137
  attributionStyle: 0.6,
2119
- metacognitivePlanning: 0.3, // Very low - impulsive, no planning
2138
+ metacognitivePlanning: 0.3, // Low - impulsive, little planning
2120
2139
  proceduralFluency: 0.4, // Inconsistent; routines help but are hard to establish
2121
2140
  transferLearning: 0.5, // Variable; depends on engagement level
2122
2141
  authoritySensitivity: 0.4, // Low - impulsive, ignores authority
@@ -2132,7 +2151,9 @@ export const ACCESSIBILITY_PERSONAS = {
2132
2151
  },
2133
2152
  "dyslexic-user": {
2134
2153
  name: "dyslexic-user",
2135
- // Research: Dyslexic adults read ~178 WPM vs 248 WPM controls (Scientific Reports 2021)
2154
+ // Research: students with dyslexia read 184.63 vs 243.64 wpm silently (Callens, Tops & Brysbaert 2012,
2155
+ // the registered rate); adults with dyslexia 178.09 vs 248.18 wpm, medians (Franzen, Stark & Johnson 2021,
2156
+ // Scientific Reports 11:6449).
2136
2157
  // About 72% of typical speed, with more fixations and regressions
2137
2158
  description: "User with dyslexia affecting reading and text processing",
2138
2159
  disabilityType: "Cognitive (Dyslexia/Reading)",
@@ -2153,7 +2174,7 @@ export const ACCESSIBILITY_PERSONAS = {
2153
2174
  reactionTime: { min: 400, max: 1000 },
2154
2175
  clickDelay: { min: 200, max: 500 },
2155
2176
  typeSpeed: { min: 80, max: 160 },
2156
- readingSpeed: 120, // Research: ~70% of normal (178/248 WPM)
2177
+ readingSpeed: displayReadingWpm("personaRate.dyslexic-user.reading"),
2157
2178
  scrollPauseTime: { min: 800, max: 2000 },
2158
2179
  },
2159
2180
  errors: {
@@ -2214,7 +2235,10 @@ export const ACCESSIBILITY_PERSONAS = {
2214
2235
  // Pulled down from 0.6 for documented secondary anxiety (Kapur & Agrawal
2215
2236
  // 2026), but not lower: the compensation literature describes adults
2216
2237
  // achieving academic success, so learned helplessness would overstate it.
2217
- resilience: 0.6,
2238
+ // (21.0: restored to the 0.5 this comment was written for. The doc
2239
+ // reconciliation of 2026-08-02 had moved it back to 0.6 by treating 0.5
2240
+ // as an unclaimed neutral, against this citation's direction.)
2241
+ resilience: 0.5,
2218
2242
  // Dyslexia is a strong predictor of lower academic self-efficacy in higher
2219
2243
  // education (PMC11488781; Nigerian undergraduate cohort).
2220
2244
  selfEfficacy: 0.3,
@@ -2277,7 +2301,7 @@ export const ACCESSIBILITY_PERSONAS = {
2277
2301
  reactionTime: { min: 200, max: 500 },
2278
2302
  clickDelay: { min: 100, max: 300 },
2279
2303
  typeSpeed: { min: 50, max: 100 },
2280
- readingSpeed: 250,
2304
+ readingSpeed: displayReadingWpm("personaRate.deaf-user.reading"),
2281
2305
  scrollPauseTime: { min: 300, max: 800 },
2282
2306
  },
2283
2307
  errors: {
@@ -2322,7 +2346,7 @@ export const ACCESSIBILITY_PERSONAS = {
2322
2346
  curiosity: 0.6,
2323
2347
  workingMemory: 0.6,
2324
2348
  informationForaging: 0.6, // Good visual navigation
2325
- changeBlindness: 0.3, // Very low - visually attentive
2349
+ changeBlindness: 0.3, // Low - visually attentive
2326
2350
  anchoringBias: 0.5,
2327
2351
  timeHorizon: 0.5,
2328
2352
  attributionStyle: 0.4, // Blames lack of captions
@@ -2330,7 +2354,7 @@ export const ACCESSIBILITY_PERSONAS = {
2330
2354
  proceduralFluency: 0.7, // Good with visual instructions
2331
2355
  transferLearning: 0.7, // Recognizes visual patterns
2332
2356
  authoritySensitivity: 0.5,
2333
- emotionalContagion: 0.6, // Less affected by audio tone
2357
+ emotionalContagion: 0.6, // Medium-high - reads visual emotional cues closely (facial expression)
2334
2358
  fearOfMissingOut: 0.4,
2335
2359
  socialProofSensitivity: 0.6, // Visual reviews/ratings
2336
2360
  mentalModelFlexibility: 0.65, // Good visual adaptation
@@ -2360,7 +2384,7 @@ export const ACCESSIBILITY_PERSONAS = {
2360
2384
  reactionTime: { min: 1000, max: 2500 },
2361
2385
  clickDelay: { min: 600, max: 1500 },
2362
2386
  typeSpeed: { min: 200, max: 400 },
2363
- readingSpeed: 80,
2387
+ readingSpeed: displayReadingWpm("personaRate.elderly-low-vision.reading"),
2364
2388
  scrollPauseTime: { min: 1000, max: 2500 },
2365
2389
  },
2366
2390
  errors: {
@@ -2417,22 +2441,22 @@ export const ACCESSIBILITY_PERSONAS = {
2417
2441
  curiosity: 0.3, // Low: prefers familiar patterns
2418
2442
  riskTolerance: 0.1, // Very cautious with unfamiliar interfaces
2419
2443
  comprehension: 0.3, // Unfamiliar with modern UI conventions
2420
- resilience: 0.6, // Low - frustration compounds with physical challenges (BRS)
2421
- selfEfficacy: 0.3, // Very low - often blame selves for tech issues (Bandura)
2444
+ resilience: 0.6, // Medium-high - adapted over time; repeated barriers still discourage (BRS)
2445
+ selfEfficacy: 0.3, // Low - often blame selves for tech issues (Bandura)
2422
2446
  satisficing: 0.7, // High - avoids complex decision trees (Simon)
2423
- trustCalibration: 0.4, // Very low - very skeptical of online requests (Fogg)
2424
- interruptRecovery: 0.3, // Very low - WM + vision decline makes recovery hard (Mark)
2447
+ trustCalibration: 0.4, // Low-medium - wary of online requests, though official-looking content can win trust (Fogg)
2448
+ interruptRecovery: 0.3, // Low - WM + vision decline makes recovery hard (Mark)
2425
2449
  // New traits (v15.0.0)
2426
2450
  readingTendency: 0.9,
2427
- informationForaging: 0.4, // Very low - exhaustive, uncertain
2451
+ informationForaging: 0.4, // Low-medium - systematic, exhaustive search
2428
2452
  changeBlindness: 0.7, // High - vision issues
2429
2453
  anchoringBias: 0.8, // High - sticks to first info
2430
2454
  timeHorizon: 0.4, // Medium - patient but unsure
2431
2455
  attributionStyle: 0.9, // Very high - blames self
2432
2456
  metacognitivePlanning: 0.2, // Low - doesn't know what to plan
2433
2457
  proceduralFluency: 0.4, // Low - struggles with sequences
2434
- transferLearning: 0.4, // Very low - each UI is confusing
2435
- authoritySensitivity: 0.7, // Very high - trusts official things
2458
+ transferLearning: 0.4, // Low-medium - each site needs new spatial and procedural learning
2459
+ authoritySensitivity: 0.7, // High - trusts official things
2436
2460
  emotionalContagion: 0.6, // Medium-high
2437
2461
  fearOfMissingOut: 0.2, // Low - not driven by urgency
2438
2462
  socialProofSensitivity: 0.7, // High - relies on family advice
@@ -2462,7 +2486,7 @@ export const ACCESSIBILITY_PERSONAS = {
2462
2486
  reactionTime: { min: 200, max: 600 }, // Slight delay on color-coded UI
2463
2487
  clickDelay: { min: 100, max: 400 },
2464
2488
  typeSpeed: { min: 50, max: 100 },
2465
- readingSpeed: 250,
2489
+ readingSpeed: displayReadingWpm("personaRate.color-blind-deuteranopia.reading"),
2466
2490
  scrollPauseTime: { min: 200, max: 500 },
2467
2491
  },
2468
2492
  errors: {
@@ -2571,7 +2595,7 @@ export const ACCESSIBILITY_PERSONAS = {
2571
2595
  reactionTime: { min: 400, max: 1200 },
2572
2596
  clickDelay: { min: 300, max: 900 },
2573
2597
  typeSpeed: { min: 80, max: 180 },
2574
- readingSpeed: 180,
2598
+ readingSpeed: displayReadingWpm("personaRate.autism-spectrum.reading"),
2575
2599
  scrollPauseTime: { min: 400, max: 1200 },
2576
2600
  },
2577
2601
  errors: {
@@ -2602,7 +2626,18 @@ export const ACCESSIBILITY_PERSONAS = {
2602
2626
  fatigueSusceptibility: 0.5, // Moderate - sensory overload increases fatigue
2603
2627
  },
2604
2628
  cognitiveTraits: {
2605
- workingMemory: 0.6, // Often good - detail-oriented (Happé & Frith 2006)
2629
+ // Norm-anchored (paper section 3.1.1): autistic adults without
2630
+ // intellectual disability score below typical controls on working
2631
+ // memory. Visuospatial WM accuracy, adult subgroup, d = -0.47, 95% CI
2632
+ // -0.91 to -0.03, 4 studies, controls matched on age and IQ, every
2633
+ // participant at IQ 70 or above (Habib et al. 2019, PLoS One
2634
+ // 14(4):e0216198, Table 6). Phi(-0.47) = 0.32, interval
2635
+ // 0.18-0.49. The adult phonological estimate is lower (d = -0.79,
2636
+ // Phi = 0.21); the smaller deficit is used. Was 0.6, "often good -
2637
+ // detail-oriented (Happe & Frith 2006)", which both adult estimates
2638
+ // exclude. Still a hypothesis: that these tasks measure this trait is
2639
+ // our mapping. research/persona-norms/applied.md.
2640
+ workingMemory: 0.32,
2606
2641
  patience: 0.65, // Moderate-high - persistent on structured tasks
2607
2642
  persistence: 0.7, // High on predictable tasks, drops on chaotic ones
2608
2643
  curiosity: 0.4, // Lower - prefers known patterns over exploration
@@ -2659,7 +2694,7 @@ export const ACCESSIBILITY_PERSONAS = {
2659
2694
  reactionTime: { min: 800, max: 2500 },
2660
2695
  clickDelay: { min: 500, max: 1500 },
2661
2696
  typeSpeed: { min: 200, max: 500 },
2662
- readingSpeed: 80, // Significantly slower
2697
+ readingSpeed: displayReadingWpm("personaRate.intellectual-disability.reading"),
2663
2698
  scrollPauseTime: { min: 800, max: 2000 },
2664
2699
  },
2665
2700
  errors: {
@@ -2696,7 +2731,7 @@ export const ACCESSIBILITY_PERSONAS = {
2696
2731
  curiosity: 0.3, // Low - prefers familiar paths
2697
2732
  riskTolerance: 0.2, // Very low - sticks to obvious elements
2698
2733
  readingTendency: 0.3, // Low - relies on images and icons
2699
- comprehension: 0.2, // Low - needs plain language
2734
+ comprehension: 0.2, // Low - needs explicit labels (UI conventions, not reading)
2700
2735
  resilience: 0.35, // Low - errors are discouraging (BRS)
2701
2736
  selfEfficacy: 0.3, // Low - often blames self for failures
2702
2737
  satisficing: 0.8, // High - takes first option that seems right
@@ -2746,7 +2781,7 @@ export const ACCESSIBILITY_PERSONAS = {
2746
2781
  reactionTime: { min: 600, max: 2000 },
2747
2782
  clickDelay: { min: 400, max: 1200 },
2748
2783
  typeSpeed: { min: 300, max: 800 }, // Text input very difficult
2749
- readingSpeed: 60, // Severely impaired language processing
2784
+ readingSpeed: displayReadingWpm("personaRate.aphasia-receptive.reading"),
2750
2785
  scrollPauseTime: { min: 600, max: 1500 },
2751
2786
  },
2752
2787
  errors: {
@@ -2783,7 +2818,7 @@ export const ACCESSIBILITY_PERSONAS = {
2783
2818
  curiosity: 0.3, // Low - new text-heavy pages are daunting
2784
2819
  riskTolerance: 0.25, // Low - unsure what labels mean
2785
2820
  readingTendency: 0.15, // Very low - avoids reading, seeks visual cues
2786
- comprehension: 0.25, // Low for text, normal for visual/spatial layouts
2821
+ comprehension: 0.25, // Low - UI conventions, not reading; the language deficit is in the reading rate
2787
2822
  resilience: 0.45, // Medium - accustomed to communication barriers
2788
2823
  selfEfficacy: 0.4, // Low-medium - knows they can think, frustrated by language
2789
2824
  satisficing: 0.7, // High - takes first visual match
@@ -2834,7 +2869,7 @@ export const ACCESSIBILITY_PERSONAS = {
2834
2869
  reactionTime: { min: 350, max: 900 },
2835
2870
  clickDelay: { min: 200, max: 500 },
2836
2871
  typeSpeed: { min: 80, max: 160 },
2837
- readingSpeed: 220, // Normal text reading speed
2872
+ readingSpeed: displayReadingWpm("personaRate.dyscalculia.reading"),
2838
2873
  scrollPauseTime: { min: 300, max: 800 },
2839
2874
  },
2840
2875
  errors: {
@@ -2874,7 +2909,7 @@ export const ACCESSIBILITY_PERSONAS = {
2874
2909
  curiosity: 0.6, // Normal - explores freely until numbers appear
2875
2910
  riskTolerance: 0.4, // Low-medium - cautious with purchases/quantities
2876
2911
  readingTendency: 0.65, // Medium-high - reads text normally, skips number-heavy sections
2877
- comprehension: 0.65, // Normal for text, low for numerical content
2912
+ comprehension: 0.65, // Medium-high - UI conventions (not reading, not numeracy)
2878
2913
  // Math anxiety is documented as intense and self-reinforcing: errors raise
2879
2914
  // anxiety, which lowers WM, which produces more errors.
2880
2915
  resilience: 0.35,
@@ -3018,7 +3053,7 @@ export const EMOTIONAL_PERSONAS = {
3018
3053
  reactionTime: { min: 400, max: 1200 }, // Slower due to deliberation
3019
3054
  clickDelay: { min: 300, max: 800 }, // Hesitates before clicking
3020
3055
  typeSpeed: { min: 80, max: 150 },
3021
- readingSpeed: 150, // Reads carefully
3056
+ readingSpeed: displayReadingWpm("personaRate.anxious-user.reading"),
3022
3057
  scrollPauseTime: { min: 400, max: 1000 },
3023
3058
  },
3024
3059
  errors: {
@@ -3041,15 +3076,15 @@ export const EMOTIONAL_PERSONAS = {
3041
3076
  },
3042
3077
  },
3043
3078
  cognitiveTraits: {
3044
- patience: 0.8, // Low - anxiety makes waiting feel worse
3079
+ patience: 0.8, // High - spends time making sure it is safe; thoroughness over speed
3045
3080
  riskTolerance: 0.2, // Very low - avoids uncertain outcomes
3046
3081
  comprehension: 0.6, // Medium - understands but worries
3047
- persistence: 0.6, // Low-medium - gives up when anxious
3082
+ persistence: 0.6, // Medium-high - persists while feeling safe; abandons when anxiety escalates
3048
3083
  curiosity: 0.3, // Low - prefers safe known paths
3049
3084
  workingMemory: 0.5, // Medium - anxiety can impair WM
3050
3085
  readingTendency: 0.9, // High - reads everything for reassurance
3051
- resilience: 0.3, // Very low - slow emotional recovery
3052
- selfEfficacy: 0.3, // Very low - doubts own abilities
3086
+ resilience: 0.3, // Low - slow emotional recovery
3087
+ selfEfficacy: 0.3, // Low - doubts own abilities
3053
3088
  satisficing: 0.3, // Low-medium - wants certainty
3054
3089
  trustCalibration: 0.2, // Low - skeptical and worried
3055
3090
  interruptRecovery: 0.4, // Low - anxiety compounds on interruption
@@ -3058,12 +3093,12 @@ export const EMOTIONAL_PERSONAS = {
3058
3093
  changeBlindness: 0.3, // Low - hypervigilant, notices changes
3059
3094
  anchoringBias: 0.7, // High - sticks to first safe option
3060
3095
  timeHorizon: 0.3, // Long-term - worries about consequences
3061
- attributionStyle: 0.7, // Very high - blames self for everything
3096
+ attributionStyle: 0.7, // High - blames self, fears being at fault
3062
3097
  metacognitivePlanning: 0.6, // Medium-high - plans to avoid anxiety
3063
3098
  proceduralFluency: 0.5, // Medium - follows carefully
3064
3099
  transferLearning: 0.4, // Medium
3065
3100
  authoritySensitivity: 0.7, // High - seeks reassurance from authority
3066
- emotionalContagion: 0.7, // Very high - absorbs UI emotional tone
3101
+ emotionalContagion: 0.7, // High - absorbs UI emotional tone
3067
3102
  fearOfMissingOut: 0.6, // Medium-high - anxiety about missing out
3068
3103
  socialProofSensitivity: 0.8, // High - seeks validation from others
3069
3104
  mentalModelFlexibility: 0.4, // Low-medium - struggles with unexpected
@@ -3095,7 +3130,7 @@ export const EMOTIONAL_PERSONAS = {
3095
3130
  reactionTime: { min: 150, max: 400 },
3096
3131
  clickDelay: { min: 80, max: 200 },
3097
3132
  typeSpeed: { min: 40, max: 100 },
3098
- readingSpeed: 300,
3133
+ readingSpeed: displayReadingWpm("personaRate.confident-user.reading"),
3099
3134
  scrollPauseTime: { min: 150, max: 400 },
3100
3135
  },
3101
3136
  errors: {
@@ -3118,7 +3153,7 @@ export const EMOTIONAL_PERSONAS = {
3118
3153
  },
3119
3154
  },
3120
3155
  cognitiveTraits: {
3121
- patience: 0.3, // Medium - not impatient but efficient
3156
+ patience: 0.3, // Low - expects quick outcomes; little tolerance for delays
3122
3157
  riskTolerance: 0.8, // High - willing to try things
3123
3158
  comprehension: 0.7, // High - understands quickly
3124
3159
  persistence: 0.7, // High - doesn't give up easily
@@ -3127,16 +3162,16 @@ export const EMOTIONAL_PERSONAS = {
3127
3162
  readingTendency: 0.2, // Low - scans efficiently
3128
3163
  resilience: 0.8, // Very high - bounces back immediately
3129
3164
  selfEfficacy: 0.9, // Very high - trusts own abilities
3130
- satisficing: 0.7, // Medium - balances speed and quality
3165
+ satisficing: 0.7, // High - accepts good-enough quickly, trusts first judgment
3131
3166
  trustCalibration: 0.7, // High - appropriate trust
3132
3167
  interruptRecovery: 0.7, // High - resumes easily
3133
3168
  // New traits (v15.0.0)
3134
3169
  informationForaging: 0.8, // High - efficient scent-following
3135
- changeBlindness: 0.6, // Low - notices changes
3170
+ changeBlindness: 0.6, // Medium-high - may miss changes while moving quickly
3136
3171
  anchoringBias: 0.3, // Low - evaluates options freely
3137
3172
  timeHorizon: 0.4, // Medium-long - thinks ahead
3138
3173
  attributionStyle: 0.2, // Low - blames system issues
3139
- metacognitivePlanning: 0.4, // High - plans efficiently
3174
+ metacognitivePlanning: 0.4, // Low-medium - minimal planning; trusts ability to adapt
3140
3175
  proceduralFluency: 0.7, // High - follows procedures well
3141
3176
  transferLearning: 0.8, // High - applies knowledge
3142
3177
  authoritySensitivity: 0.3, // Low-medium - independent judgment
@@ -3172,7 +3207,7 @@ export const EMOTIONAL_PERSONAS = {
3172
3207
  reactionTime: { min: 150, max: 600 }, // Variable based on mood
3173
3208
  clickDelay: { min: 100, max: 400 },
3174
3209
  typeSpeed: { min: 50, max: 130 },
3175
- readingSpeed: 220,
3210
+ readingSpeed: displayReadingWpm("personaRate.emotional-user.reading"),
3176
3211
  scrollPauseTime: { min: 200, max: 600 },
3177
3212
  },
3178
3213
  errors: {
@@ -3202,7 +3237,7 @@ export const EMOTIONAL_PERSONAS = {
3202
3237
  curiosity: 0.6, // Medium-high - excitement drives exploration
3203
3238
  workingMemory: 0.5, // Medium - emotions can interfere
3204
3239
  readingTendency: 0.6, // Medium
3205
- resilience: 0.4, // Very low - emotions linger long
3240
+ resilience: 0.4, // Low-medium - negative experiences linger
3206
3241
  selfEfficacy: 0.5, // Medium - mood dependent
3207
3242
  satisficing: 0.6, // Medium-high - wants quick resolution
3208
3243
  trustCalibration: 0.5, // Medium - emotional judgment
@@ -3249,7 +3284,7 @@ export const EMOTIONAL_PERSONAS = {
3249
3284
  reactionTime: { min: 250, max: 600 },
3250
3285
  clickDelay: { min: 150, max: 350 },
3251
3286
  typeSpeed: { min: 60, max: 120 },
3252
- readingSpeed: 220,
3287
+ readingSpeed: displayReadingWpm("personaRate.stoic-user.reading"),
3253
3288
  scrollPauseTime: { min: 250, max: 600 },
3254
3289
  },
3255
3290
  errors: {
@@ -3272,14 +3307,14 @@ export const EMOTIONAL_PERSONAS = {
3272
3307
  },
3273
3308
  },
3274
3309
  cognitiveTraits: {
3275
- patience: 0.7, // Very high - doesn't rush
3310
+ patience: 0.7, // High - doesn't rush
3276
3311
  riskTolerance: 0.5, // Medium - balanced judgment
3277
3312
  comprehension: 0.7, // High - clear thinking
3278
- persistence: 0.7, // Very high - never gives up
3313
+ persistence: 0.7, // High - persistent, not emotionally deterred
3279
3314
  curiosity: 0.4, // Medium - methodical exploration
3280
3315
  workingMemory: 0.7, // High - unaffected by emotion
3281
3316
  readingTendency: 0.7, // Medium-high - thorough
3282
- resilience: 0.8, // Maximum - emotions barely register
3317
+ resilience: 0.8, // Very high - errors are data points, not emotional events
3283
3318
  selfEfficacy: 0.6, // High - quiet confidence
3284
3319
  satisficing: 0.4, // Low - willing to be thorough
3285
3320
  trustCalibration: 0.7, // Medium-high - rational evaluation
@@ -3294,8 +3329,8 @@ export const EMOTIONAL_PERSONAS = {
3294
3329
  proceduralFluency: 0.6, // High - follows procedures precisely
3295
3330
  transferLearning: 0.7, // High - applies experience
3296
3331
  authoritySensitivity: 0.4, // Low-medium - independent judgment
3297
- emotionalContagion: 0.2, // Minimum - emotionally unaffected
3298
- fearOfMissingOut: 0.2, // Minimum - not driven by urgency
3332
+ emotionalContagion: 0.2, // Very low - emotionally unaffected
3333
+ fearOfMissingOut: 0.2, // Very low - not driven by urgency
3299
3334
  socialProofSensitivity: 0.4, // Low - evaluates independently
3300
3335
  mentalModelFlexibility: 0.7, // High - adapts methodically
3301
3336
  },