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.
- package/README.md +2 -2
- package/dist/analysis/accessibility-empathy.d.ts +29 -1
- package/dist/analysis/accessibility-empathy.d.ts.map +1 -1
- package/dist/analysis/accessibility-empathy.js +69 -35
- package/dist/analysis/accessibility-empathy.js.map +1 -1
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +11 -7
- package/dist/browser.js.map +1 -1
- package/dist/cif-score.d.ts +56 -5
- package/dist/cif-score.d.ts.map +1 -1
- package/dist/cif-score.js +595 -346
- package/dist/cif-score.js.map +1 -1
- package/dist/cli.js +10 -8
- package/dist/cli.js.map +1 -1
- package/dist/cognitive/default-traits.d.ts +14 -0
- package/dist/cognitive/default-traits.d.ts.map +1 -0
- package/dist/cognitive/default-traits.js +36 -0
- package/dist/cognitive/default-traits.js.map +1 -0
- package/dist/cognitive/emotions.d.ts.map +1 -1
- package/dist/cognitive/emotions.js +104 -174
- package/dist/cognitive/emotions.js.map +1 -1
- package/dist/cognitive/index.d.ts +28 -0
- package/dist/cognitive/index.d.ts.map +1 -1
- package/dist/cognitive/index.js +353 -287
- package/dist/cognitive/index.js.map +1 -1
- package/dist/cognitive/temporal.d.ts +0 -24
- package/dist/cognitive/temporal.d.ts.map +1 -1
- package/dist/cognitive/temporal.js +45 -35
- package/dist/cognitive/temporal.js.map +1 -1
- package/dist/data/ctc-reference-v2-2026-10-24.d.ts +16 -0
- package/dist/data/ctc-reference-v2-2026-10-24.d.ts.map +1 -0
- package/dist/data/ctc-reference-v2-2026-10-24.js +1004 -0
- package/dist/data/ctc-reference-v2-2026-10-24.js.map +1 -0
- package/dist/ideal-profiles-gap.d.ts +1 -0
- package/dist/ideal-profiles-gap.d.ts.map +1 -1
- package/dist/ideal-profiles-gap.js +9 -1
- package/dist/ideal-profiles-gap.js.map +1 -1
- package/dist/ideal-profiles.d.ts +8 -0
- package/dist/ideal-profiles.d.ts.map +1 -1
- package/dist/ideal-profiles.js +28 -24
- package/dist/ideal-profiles.js.map +1 -1
- package/dist/mcp-server-remote.d.ts.map +1 -1
- package/dist/mcp-server-remote.js +7 -8
- package/dist/mcp-server-remote.js.map +1 -1
- package/dist/mcp-tools/account-personas.d.ts.map +1 -1
- package/dist/mcp-tools/account-personas.js +3 -1
- package/dist/mcp-tools/account-personas.js.map +1 -1
- package/dist/mcp-tools/base/answer-provenance.d.ts +28 -0
- package/dist/mcp-tools/base/answer-provenance.d.ts.map +1 -0
- package/dist/mcp-tools/base/answer-provenance.js +32 -0
- package/dist/mcp-tools/base/answer-provenance.js.map +1 -0
- package/dist/mcp-tools/base/audit-tools.d.ts +0 -3
- package/dist/mcp-tools/base/audit-tools.d.ts.map +1 -1
- package/dist/mcp-tools/base/audit-tools.js +152 -84
- package/dist/mcp-tools/base/audit-tools.js.map +1 -1
- package/dist/mcp-tools/base/capture-tools.js +1 -1
- package/dist/mcp-tools/base/capture-tools.js.map +1 -1
- package/dist/mcp-tools/base/chain-values.d.ts +38 -0
- package/dist/mcp-tools/base/chain-values.d.ts.map +1 -0
- package/dist/mcp-tools/base/chain-values.js +85 -0
- package/dist/mcp-tools/base/chain-values.js.map +1 -0
- package/dist/mcp-tools/base/cognitive-tools.d.ts.map +1 -1
- package/dist/mcp-tools/base/cognitive-tools.js +126 -120
- package/dist/mcp-tools/base/cognitive-tools.js.map +1 -1
- package/dist/mcp-tools/base/gif-tools.d.ts.map +1 -1
- package/dist/mcp-tools/base/gif-tools.js +23 -5
- package/dist/mcp-tools/base/gif-tools.js.map +1 -1
- package/dist/mcp-tools/base/persona-comparison-tools.d.ts.map +1 -1
- package/dist/mcp-tools/base/persona-comparison-tools.js +229 -172
- package/dist/mcp-tools/base/persona-comparison-tools.js.map +1 -1
- package/dist/mcp-tools/base/site-familiarity.d.ts +31 -0
- package/dist/mcp-tools/base/site-familiarity.d.ts.map +1 -0
- package/dist/mcp-tools/base/site-familiarity.js +30 -0
- package/dist/mcp-tools/base/site-familiarity.js.map +1 -0
- package/dist/mcp-tools/base/site-knowledge-tools.js +1 -1
- package/dist/mcp-tools/base/site-knowledge-tools.js.map +1 -1
- package/dist/mcp-tools/base/story-narrative.d.ts +50 -0
- package/dist/mcp-tools/base/story-narrative.d.ts.map +1 -0
- package/dist/mcp-tools/base/story-narrative.js +88 -0
- package/dist/mcp-tools/base/story-narrative.js.map +1 -0
- package/dist/mcp-tools/base/values-tools.d.ts.map +1 -1
- package/dist/mcp-tools/base/values-tools.js +19 -5
- package/dist/mcp-tools/base/values-tools.js.map +1 -1
- package/dist/mcp-tools/base/visual-testing-tools.d.ts +5 -5
- package/dist/mcp-tools/base/visual-testing-tools.d.ts.map +1 -1
- package/dist/mcp-tools/base/visual-testing-tools.js +38 -11
- package/dist/mcp-tools/base/visual-testing-tools.js.map +1 -1
- package/dist/mcp-tools/persona-creation-tools.js +6 -6
- package/dist/mcp-tools/persona-creation-tools.js.map +1 -1
- package/dist/mcp-tools/persona-lifecycle-tools.d.ts.map +1 -1
- package/dist/mcp-tools/persona-lifecycle-tools.js +5 -1
- package/dist/mcp-tools/persona-lifecycle-tools.js.map +1 -1
- package/dist/mcp-tools/tier-gate.js +1 -1
- package/dist/mcp-tools/tool-result-saver.d.ts +7 -0
- package/dist/mcp-tools/tool-result-saver.d.ts.map +1 -1
- package/dist/mcp-tools/tool-result-saver.js +11 -0
- package/dist/mcp-tools/tool-result-saver.js.map +1 -1
- package/dist/mcp-tools/trait-provenance.d.ts +109 -0
- package/dist/mcp-tools/trait-provenance.d.ts.map +1 -0
- package/dist/mcp-tools/trait-provenance.js +187 -0
- package/dist/mcp-tools/trait-provenance.js.map +1 -0
- package/dist/mcp-tools/ui-resources.d.ts +6 -7
- package/dist/mcp-tools/ui-resources.d.ts.map +1 -1
- package/dist/mcp-tools/ui-resources.js +162 -12
- package/dist/mcp-tools/ui-resources.js.map +1 -1
- package/dist/mcp-tools/widget-kit.d.ts +129 -3
- package/dist/mcp-tools/widget-kit.d.ts.map +1 -1
- package/dist/mcp-tools/widget-kit.js +507 -28
- package/dist/mcp-tools/widget-kit.js.map +1 -1
- package/dist/performance/metrics.d.ts.map +1 -1
- package/dist/performance/metrics.js +4 -1
- package/dist/performance/metrics.js.map +1 -1
- package/dist/persona-age.d.ts +59 -0
- package/dist/persona-age.d.ts.map +1 -0
- package/dist/persona-age.js +84 -0
- package/dist/persona-age.js.map +1 -0
- package/dist/persona-questionnaire.js +1 -1
- package/dist/persona-questionnaire.js.map +1 -1
- package/dist/personas.d.ts +3 -1
- package/dist/personas.d.ts.map +1 -1
- package/dist/personas.js +154 -119
- package/dist/personas.js.map +1 -1
- package/dist/recording/engine.d.ts.map +1 -1
- package/dist/recording/engine.js +5 -2
- package/dist/recording/engine.js.map +1 -1
- package/dist/recording/saliency-overlay.d.ts +8 -3
- package/dist/recording/saliency-overlay.d.ts.map +1 -1
- package/dist/recording/saliency-overlay.js +14 -5
- package/dist/recording/saliency-overlay.js.map +1 -1
- package/dist/recording/types.js +1 -1
- package/dist/testing/nl-test-suite.d.ts.map +1 -1
- package/dist/testing/nl-test-suite.js +2 -1
- package/dist/testing/nl-test-suite.js.map +1 -1
- package/dist/trait-reference.d.ts +19 -2
- package/dist/trait-reference.d.ts.map +1 -1
- package/dist/trait-reference.js +19 -2
- package/dist/trait-reference.js.map +1 -1
- package/dist/types.d.ts +32 -21
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +62 -52
- package/dist/types.js.map +1 -1
- package/dist/values/persona-completeness.js +1 -1
- package/dist/values/persona-completeness.js.map +1 -1
- package/dist/visual/ab-comparison.d.ts.map +1 -1
- package/dist/visual/ab-comparison.js +4 -1
- package/dist/visual/ab-comparison.js.map +1 -1
- package/dist/visual/attention-quality.d.ts +1 -1
- package/dist/visual/attention-quality.js +1 -1
- package/dist/visual/attention-transport.d.ts +74 -10
- package/dist/visual/attention-transport.d.ts.map +1 -1
- package/dist/visual/attention-transport.js +353 -193
- package/dist/visual/attention-transport.js.map +1 -1
- package/dist/visual/cognitive-models.d.ts +77 -55
- package/dist/visual/cognitive-models.d.ts.map +1 -1
- package/dist/visual/cognitive-models.js +231 -104
- package/dist/visual/cognitive-models.js.map +1 -1
- package/dist/visual/cognitive-transport-chain.d.ts +328 -30
- package/dist/visual/cognitive-transport-chain.d.ts.map +1 -1
- package/dist/visual/cognitive-transport-chain.js +576 -353
- package/dist/visual/cognitive-transport-chain.js.map +1 -1
- package/dist/visual/cognitive-transport.d.ts +446 -13
- package/dist/visual/cognitive-transport.d.ts.map +1 -1
- package/dist/visual/cognitive-transport.js +1085 -245
- package/dist/visual/cognitive-transport.js.map +1 -1
- package/dist/visual/cross-browser.d.ts.map +1 -1
- package/dist/visual/cross-browser.js +8 -6
- package/dist/visual/cross-browser.js.map +1 -1
- package/dist/visual/ctc-bands.d.ts +91 -0
- package/dist/visual/ctc-bands.d.ts.map +1 -0
- package/dist/visual/ctc-bands.js +117 -0
- package/dist/visual/ctc-bands.js.map +1 -0
- package/dist/visual/ctc-reference.d.ts +287 -0
- package/dist/visual/ctc-reference.d.ts.map +1 -0
- package/dist/visual/ctc-reference.js +376 -0
- package/dist/visual/ctc-reference.js.map +1 -0
- package/dist/visual/demand-laws.d.ts +145 -0
- package/dist/visual/demand-laws.d.ts.map +1 -0
- package/dist/visual/demand-laws.js +220 -0
- package/dist/visual/demand-laws.js.map +1 -0
- package/dist/visual/distance-metrics.d.ts +23 -1
- package/dist/visual/distance-metrics.d.ts.map +1 -1
- package/dist/visual/distance-metrics.js +49 -18
- package/dist/visual/distance-metrics.js.map +1 -1
- package/dist/visual/dro-bound.d.ts +220 -0
- package/dist/visual/dro-bound.d.ts.map +1 -0
- package/dist/visual/dro-bound.js +341 -0
- package/dist/visual/dro-bound.js.map +1 -0
- package/dist/visual/exact-w1.d.ts +60 -0
- package/dist/visual/exact-w1.d.ts.map +1 -0
- package/dist/visual/exact-w1.js +247 -0
- package/dist/visual/exact-w1.js.map +1 -0
- package/dist/visual/human-input.d.ts.map +1 -1
- package/dist/visual/human-input.js +45 -41
- package/dist/visual/human-input.js.map +1 -1
- package/dist/visual/index.d.ts +2 -0
- package/dist/visual/index.d.ts.map +1 -1
- package/dist/visual/index.js +2 -0
- package/dist/visual/index.js.map +1 -1
- package/dist/visual/law-times-report.d.ts +49 -0
- package/dist/visual/law-times-report.d.ts.map +1 -0
- package/dist/visual/law-times-report.js +38 -0
- package/dist/visual/law-times-report.js.map +1 -0
- package/dist/visual/model-provenance.d.ts +151 -0
- package/dist/visual/model-provenance.d.ts.map +1 -0
- package/dist/visual/model-provenance.js +335 -0
- package/dist/visual/model-provenance.js.map +1 -0
- package/dist/visual/normal-cdf.d.ts +14 -0
- package/dist/visual/normal-cdf.d.ts.map +1 -0
- package/dist/visual/normal-cdf.js +26 -0
- package/dist/visual/normal-cdf.js.map +1 -0
- package/dist/visual/perceptual-transport.d.ts +28 -4
- package/dist/visual/perceptual-transport.d.ts.map +1 -1
- package/dist/visual/perceptual-transport.js +66 -32
- package/dist/visual/perceptual-transport.js.map +1 -1
- package/dist/visual/provenance/age.d.ts +30 -0
- package/dist/visual/provenance/age.d.ts.map +1 -0
- package/dist/visual/provenance/age.js +28 -0
- package/dist/visual/provenance/age.js.map +1 -0
- package/dist/visual/provenance/attention.d.ts +55 -0
- package/dist/visual/provenance/attention.d.ts.map +1 -0
- package/dist/visual/provenance/attention.js +188 -0
- package/dist/visual/provenance/attention.js.map +1 -0
- package/dist/visual/provenance/chain.d.ts +41 -0
- package/dist/visual/provenance/chain.d.ts.map +1 -0
- package/dist/visual/provenance/chain.js +66 -0
- package/dist/visual/provenance/chain.js.map +1 -0
- package/dist/visual/provenance/cif.d.ts +42 -0
- package/dist/visual/provenance/cif.d.ts.map +1 -0
- package/dist/visual/provenance/cif.js +116 -0
- package/dist/visual/provenance/cif.js.map +1 -0
- package/dist/visual/provenance/ctc-reference.d.ts +36 -0
- package/dist/visual/provenance/ctc-reference.d.ts.map +1 -0
- package/dist/visual/provenance/ctc-reference.js +96 -0
- package/dist/visual/provenance/ctc-reference.js.map +1 -0
- package/dist/visual/provenance/distance.d.ts +10 -0
- package/dist/visual/provenance/distance.d.ts.map +1 -0
- package/dist/visual/provenance/distance.js +72 -0
- package/dist/visual/provenance/distance.js.map +1 -0
- package/dist/visual/provenance/dro.d.ts +10 -0
- package/dist/visual/provenance/dro.d.ts.map +1 -0
- package/dist/visual/provenance/dro.js +2 -0
- package/dist/visual/provenance/dro.js.map +1 -0
- package/dist/visual/provenance/emotion.d.ts +26 -0
- package/dist/visual/provenance/emotion.d.ts.map +1 -0
- package/dist/visual/provenance/emotion.js +99 -0
- package/dist/visual/provenance/emotion.js.map +1 -0
- package/dist/visual/provenance/human-input.d.ts +19 -0
- package/dist/visual/provenance/human-input.d.ts.map +1 -0
- package/dist/visual/provenance/human-input.js +84 -0
- package/dist/visual/provenance/human-input.js.map +1 -0
- package/dist/visual/provenance/journey-group.d.ts +15 -0
- package/dist/visual/provenance/journey-group.d.ts.map +1 -0
- package/dist/visual/provenance/journey-group.js +15 -0
- package/dist/visual/provenance/journey-group.js.map +1 -0
- package/dist/visual/provenance/journey-mcp.d.ts +24 -0
- package/dist/visual/provenance/journey-mcp.d.ts.map +1 -0
- package/dist/visual/provenance/journey-mcp.js +54 -0
- package/dist/visual/provenance/journey-mcp.js.map +1 -0
- package/dist/visual/provenance/journey.d.ts +34 -0
- package/dist/visual/provenance/journey.d.ts.map +1 -0
- package/dist/visual/provenance/journey.js +184 -0
- package/dist/visual/provenance/journey.js.map +1 -0
- package/dist/visual/provenance/laws.d.ts +38 -0
- package/dist/visual/provenance/laws.d.ts.map +1 -0
- package/dist/visual/provenance/laws.js +40 -0
- package/dist/visual/provenance/laws.js.map +1 -0
- package/dist/visual/provenance/page-metrics.d.ts +42 -0
- package/dist/visual/provenance/page-metrics.d.ts.map +1 -0
- package/dist/visual/provenance/page-metrics.js +79 -0
- package/dist/visual/provenance/page-metrics.js.map +1 -0
- package/dist/visual/provenance/perceptual.d.ts +63 -0
- package/dist/visual/provenance/perceptual.d.ts.map +1 -0
- package/dist/visual/provenance/perceptual.js +115 -0
- package/dist/visual/provenance/perceptual.js.map +1 -0
- package/dist/visual/provenance/persona-rates.d.ts +84 -0
- package/dist/visual/provenance/persona-rates.d.ts.map +1 -0
- package/dist/visual/provenance/persona-rates.js +108 -0
- package/dist/visual/provenance/persona-rates.js.map +1 -0
- package/dist/visual/provenance/personas.d.ts +122 -0
- package/dist/visual/provenance/personas.d.ts.map +1 -0
- package/dist/visual/provenance/personas.js +298 -0
- package/dist/visual/provenance/personas.js.map +1 -0
- package/dist/visual/provenance/profiles.d.ts +39 -0
- package/dist/visual/provenance/profiles.d.ts.map +1 -0
- package/dist/visual/provenance/profiles.js +37 -0
- package/dist/visual/provenance/profiles.js.map +1 -0
- package/dist/visual/provenance/temporal.d.ts +21 -0
- package/dist/visual/provenance/temporal.d.ts.map +1 -0
- package/dist/visual/provenance/temporal.js +56 -0
- package/dist/visual/provenance/temporal.js.map +1 -0
- package/dist/visual/provenance/visual-distance.d.ts +22 -0
- package/dist/visual/provenance/visual-distance.d.ts.map +1 -0
- package/dist/visual/provenance/visual-distance.js +30 -0
- package/dist/visual/provenance/visual-distance.js.map +1 -0
- package/dist/visual/regression.d.ts.map +1 -1
- package/dist/visual/regression.js +14 -9
- package/dist/visual/regression.js.map +1 -1
- package/dist/visual/responsive.d.ts.map +1 -1
- package/dist/visual/responsive.js +4 -1
- package/dist/visual/responsive.js.map +1 -1
- package/dist/visual/scope-prose.js +2 -2
- package/dist/visual/scope-prose.js.map +1 -1
- package/dist/visual/seeded-random.d.ts +16 -0
- package/dist/visual/seeded-random.d.ts.map +1 -0
- package/dist/visual/seeded-random.js +25 -0
- package/dist/visual/seeded-random.js.map +1 -0
- package/dist/visual/stored-accessibility-traits.d.ts +27 -0
- package/dist/visual/stored-accessibility-traits.d.ts.map +1 -0
- package/dist/visual/stored-accessibility-traits.js +35 -0
- package/dist/visual/stored-accessibility-traits.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { PERCEPTUAL_PROFILES, DEFAULT_PROFILE } from "../perceptual-transport.js";
|
|
2
|
+
/** Per barrier key: the barrier, as a reader would name it. */
|
|
3
|
+
const BARRIERS = {
|
|
4
|
+
touch_target: "small or crowded touch and click target",
|
|
5
|
+
low_contrast: "low-contrast text",
|
|
6
|
+
cognitive_load: "high cognitive load (dense or complex layout)",
|
|
7
|
+
timing: "time limit or timed content",
|
|
8
|
+
color_only: "information carried by colour alone",
|
|
9
|
+
missing_alt: "image without a text alternative",
|
|
10
|
+
missing_label: "form field without a label",
|
|
11
|
+
hover_dependent: "content reachable only by hover",
|
|
12
|
+
form_complexity: "long or complex form",
|
|
13
|
+
audio_description: "video without audio description",
|
|
14
|
+
captions: "media without captions",
|
|
15
|
+
};
|
|
16
|
+
/** Per visual-filter field: what it models and the measure that would place a population on it. */
|
|
17
|
+
const FILTER_FIELDS = {
|
|
18
|
+
contrastThreshold: { what: "minimum contrast perceived", measure: "Pelli-Robson contrast sensitivity" },
|
|
19
|
+
blurRadius: { what: "blur simulating reduced acuity", measure: "visual acuity (logMAR) at a stated viewing distance, converted to screen pixels" },
|
|
20
|
+
"colorAttenuation.r": { what: "red-channel attenuation", measure: "axis-specific colour discrimination (e.g. Farnsworth-Munsell 100-hue, protan axis)" },
|
|
21
|
+
"colorAttenuation.g": { what: "green-channel attenuation", measure: "axis-specific colour discrimination (e.g. Farnsworth-Munsell 100-hue, deutan axis)" },
|
|
22
|
+
"colorAttenuation.b": { what: "blue-channel attenuation", measure: "axis-specific colour discrimination (e.g. Farnsworth-Munsell 100-hue, tritan axis)" },
|
|
23
|
+
motorCostMultiplier: { what: "cost of reaching interactive elements, relative to typical", measure: "pointing throughput on an ISO 9241-411 tapping task, as a ratio to a typical sample" },
|
|
24
|
+
processingSpeed: { what: "processing speed, relative to typical (it attenuates weak saliency in the attention map)", measure: "the Symbol Digit Modalities Test, as a ratio to the norm" },
|
|
25
|
+
noiseTolerance: { what: "tolerance of visual clutter", measure: "the slowdown of visual search on cluttered against uncluttered displays" },
|
|
26
|
+
};
|
|
27
|
+
/** Per profile: the population a test sample would come from, or the archetype's screening criterion. */
|
|
28
|
+
const POPULATIONS = {
|
|
29
|
+
"first-timer": { population: "adults using the interface under test for the first time" },
|
|
30
|
+
"mobile-user": { population: "smartphone-primary web users aged 18-45" },
|
|
31
|
+
"impatient-user": { archetype: "users in the top quartile of observed abandonment rate" },
|
|
32
|
+
"power-user": { population: "expert daily web users (e.g. professional developers) aged 25-45" },
|
|
33
|
+
"elderly-user": { population: "adults aged 65 and over" },
|
|
34
|
+
"motor-impairment-tremor": { population: "adults aged 40-65 with essential tremor" },
|
|
35
|
+
"low-vision-magnified": { population: "adults aged 45-75 with low vision who use about 3x screen magnification" },
|
|
36
|
+
"cognitive-adhd": { population: "adults aged 18-45 diagnosed with ADHD" },
|
|
37
|
+
"dyslexic-user": { population: "adults aged 18-55 diagnosed with dyslexia" },
|
|
38
|
+
"color-blind-deuteranopia": { population: "adults with confirmed deuteranopia" },
|
|
39
|
+
"screen-reader-user": { population: "blind adults who use a screen reader daily" },
|
|
40
|
+
"deaf-user": { population: "deaf adults" },
|
|
41
|
+
"elderly-low-vision": { population: "adults aged 75 and over with age-related low vision" },
|
|
42
|
+
};
|
|
43
|
+
const DEFAULT_ID = "default";
|
|
44
|
+
function sample(profile) {
|
|
45
|
+
const who = POPULATIONS[profile];
|
|
46
|
+
return "population" in who
|
|
47
|
+
? `a sample of ${who.population}`
|
|
48
|
+
: `a sample screened as ${who.archetype} (the profile is a behavioural archetype with no population until then)`;
|
|
49
|
+
}
|
|
50
|
+
function barrierSource(profile, key, value) {
|
|
51
|
+
if (profile === DEFAULT_ID) {
|
|
52
|
+
return `DEFAULT_PROFILE.${key} = ${value}: a ${BARRIERS[key]} is charged at face value for a persona no profile describes. The neutral weight of a profile that models no one; no empirical claim.`;
|
|
53
|
+
}
|
|
54
|
+
return `${profile} barrier weight ${key} = ${value}, set by hand: the multiple of the points one ${BARRIERS[key]} deducts for this persona. What would fit it: the drop in task success (or rise in time on task) one such barrier costs ${sample(profile)}, divided by the drop it costs a general-population sample, on otherwise matched pages.`;
|
|
55
|
+
}
|
|
56
|
+
function filterSource(profile, field, value) {
|
|
57
|
+
const f = FILTER_FIELDS[field];
|
|
58
|
+
if (profile === DEFAULT_ID) {
|
|
59
|
+
return `DEFAULT_PROFILE visual filter ${field} = ${value} (${f.what}): the identity filter of a profile that models no one; no empirical claim.`;
|
|
60
|
+
}
|
|
61
|
+
return `${profile} visual filter ${field} = ${value} (${f.what}), set by hand. What would test it: ${f.measure}, in ${sample(profile)}.`;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Build one entry per numeric barrier weight and visual-filter field. A value
|
|
65
|
+
* whose profile, barrier key or field this file has no description for is
|
|
66
|
+
* reported as uncovered instead of registered, so the test fails rather than
|
|
67
|
+
* the module.
|
|
68
|
+
*/
|
|
69
|
+
export function cataloguePerceptualProfiles(profiles, defaultProfile) {
|
|
70
|
+
const entries = [];
|
|
71
|
+
const uncovered = [];
|
|
72
|
+
const seen = new Set();
|
|
73
|
+
const add = (id, value, known, status, source) => {
|
|
74
|
+
if (seen.has(id) || !known) {
|
|
75
|
+
uncovered.push(id);
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
seen.add(id);
|
|
79
|
+
entries.push({ id, value, status, source: source() });
|
|
80
|
+
};
|
|
81
|
+
const all = [...Object.entries(profiles), [DEFAULT_ID, defaultProfile]];
|
|
82
|
+
for (const [name, profile] of all) {
|
|
83
|
+
const isDefault = name === DEFAULT_ID && profile === defaultProfile;
|
|
84
|
+
const knownProfile = isDefault || (name !== DEFAULT_ID && Object.hasOwn(POPULATIONS, name));
|
|
85
|
+
const status = isDefault ? "definition" : "hypothesis";
|
|
86
|
+
for (const [key, value] of Object.entries(profile.barrierWeights)) {
|
|
87
|
+
if (typeof value !== "number")
|
|
88
|
+
continue;
|
|
89
|
+
add(`perceptual.${name}.barrierWeights.${key}`, value, knownProfile && Object.hasOwn(BARRIERS, key), status, () => barrierSource(name, key, value));
|
|
90
|
+
}
|
|
91
|
+
const filter = profile.visualFilter;
|
|
92
|
+
for (const [field, value] of Object.entries(filter)) {
|
|
93
|
+
const leaves = Array.isArray(value)
|
|
94
|
+
? value.map((v, i) => [`${field}.${"rgb"[i] ?? i}`, v])
|
|
95
|
+
: [[field, value]];
|
|
96
|
+
for (const [leaf, v] of leaves) {
|
|
97
|
+
if (typeof v !== "number")
|
|
98
|
+
continue;
|
|
99
|
+
add(`perceptual.${name}.visualFilter.${leaf}`, v, knownProfile && Object.hasOwn(FILTER_FIELDS, leaf), status, () => filterSource(name, leaf, v));
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return { entries, uncovered };
|
|
104
|
+
}
|
|
105
|
+
const CATALOGUE = cataloguePerceptualProfiles(PERCEPTUAL_PROFILES, DEFAULT_PROFILE);
|
|
106
|
+
export const PERCEPTUAL_PROVENANCE = CATALOGUE.entries;
|
|
107
|
+
/** Numeric fields in the profiles this file cannot describe yet. Must be empty; the test says which. */
|
|
108
|
+
export const PERCEPTUAL_PROVENANCE_UNCOVERED = CATALOGUE.uncovered;
|
|
109
|
+
/** The keys of the hand-written tables above, so the test can catch a stale one. */
|
|
110
|
+
export const PERCEPTUAL_PROVENANCE_KEYS = {
|
|
111
|
+
barriers: Object.keys(BARRIERS),
|
|
112
|
+
filterFields: Object.keys(FILTER_FIELDS),
|
|
113
|
+
populations: Object.keys(POPULATIONS),
|
|
114
|
+
};
|
|
115
|
+
//# sourceMappingURL=perceptual.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"perceptual.js","sourceRoot":"","sources":["../../../src/visual/provenance/perceptual.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Each built-in persona's pointing and reading rate, as a share of the
|
|
3
|
+
* reference rate: the r_p / r_ref a capacity c = r_p / (r_p + r_ref) is built
|
|
4
|
+
* from (demand-laws.ts, rateCapacity). See ../model-provenance.ts for the
|
|
5
|
+
* statuses.
|
|
6
|
+
*
|
|
7
|
+
* WHY ON THE PERSONA. Four personas state all five reading-profile values in
|
|
8
|
+
* their accessibilityTraits, so the reading-profile table never reaches them,
|
|
9
|
+
* and twenty get a throughput by interpolating on dispositions. A rate per
|
|
10
|
+
* persona, registered here with its own status and source, is the one place
|
|
11
|
+
* a decision about that persona's rate lands. A custom persona has no entry;
|
|
12
|
+
* its rates come from the profiles (provenance/profiles.ts).
|
|
13
|
+
*
|
|
14
|
+
* The values follow the persona-rate decisions of 2026-10-23
|
|
15
|
+
* (research/stage-b-persona-rates.md):
|
|
16
|
+
* pointing tremor: the motion-impaired rate against its own controls;
|
|
17
|
+
* elderly (two personas): the elderly profile, a hypothesis;
|
|
18
|
+
* cognitive-adhd: the reference, a hypothesis (no measured rate);
|
|
19
|
+
* mobile-user: unchanged until touch is modelled;
|
|
20
|
+
* every other persona: the reference, "no measured difference".
|
|
21
|
+
* reading dyslexic-user: the dyslexia rate against its own controls;
|
|
22
|
+
* low-vision-magnified, elderly-low-vision: low vision with intact
|
|
23
|
+
* central fields against the reference rate;
|
|
24
|
+
* aphasia-receptive: aphasia with impaired reading comprehension
|
|
25
|
+
* against age-matched controls (Webster et al. 2018, Stage C);
|
|
26
|
+
* elderly-user, cognitive-adhd: today's fixation-model slowdown,
|
|
27
|
+
* a hypothesis; intellectual-disability: its pre-21.0 share,
|
|
28
|
+
* frozen as a number, a hypothesis;
|
|
29
|
+
* every other persona: the reference, "no measured difference".
|
|
30
|
+
*
|
|
31
|
+
* A measured ratio is `published` only when the population and its control
|
|
32
|
+
* were measured in the same study by the same method. The low-vision rate
|
|
33
|
+
* against 238 wpm crosses methods (a peak rate on drifting text against a
|
|
34
|
+
* meta-analytic silent reading rate), so it is a hypothesis built on two
|
|
35
|
+
* published numbers. Ratios are computed here from the registered numbers they
|
|
36
|
+
* come from, so the two cannot disagree; the bridge reads them through param()
|
|
37
|
+
* (cognitive-models.ts), unrecorded, like the persona's catalogued traits.
|
|
38
|
+
* tests/persona-capacity-rates.test.ts fails if a built-in persona has no
|
|
39
|
+
* entry on a channel, or an entry names no built-in persona.
|
|
40
|
+
*
|
|
41
|
+
* CUSTOM PERSONAS (customRate.*) take the same rule as the built-ins, decided
|
|
42
|
+
* 2026-10-23: the reference rate where nothing is measured ("no measured
|
|
43
|
+
* difference"), a measured ratio where one is. The rule reads what a stored
|
|
44
|
+
* custom persona carries: the tremor flag, and words in its name and
|
|
45
|
+
* description (customPointingRule, customReadingRule; an elderly cue reads the
|
|
46
|
+
* built-in elderly-user's reading entry). An author's stated
|
|
47
|
+
* reading-profile values are honoured first, through the fixation-model
|
|
48
|
+
* ratio (cognitive-models.ts, readingRateShare), labelled hypothesis.
|
|
49
|
+
*
|
|
50
|
+
* @copyright 2026 Alexandria Eden alexandria.shai.eden@gmail.com https://cbrowser.ai
|
|
51
|
+
* @license MIT
|
|
52
|
+
*/
|
|
53
|
+
import type { ProvenanceEntry } from "../model-provenance.js";
|
|
54
|
+
export declare const PERSONA_RATE_PROVENANCE: ProvenanceEntry[];
|
|
55
|
+
export declare const CUSTOM_RATE_PROVENANCE: ProvenanceEntry[];
|
|
56
|
+
/** Which customRate.* pointing rule a custom persona falls under. */
|
|
57
|
+
export declare function customPointingRule(p: {
|
|
58
|
+
name?: string;
|
|
59
|
+
description?: string;
|
|
60
|
+
tremor?: unknown;
|
|
61
|
+
ageRange?: string;
|
|
62
|
+
}): "tremor" | "elderly" | "noMeasuredDifference";
|
|
63
|
+
/** Which reading rule a custom persona with no stated reading-profile values falls under. */
|
|
64
|
+
export declare function customReadingRule(p: {
|
|
65
|
+
name?: string;
|
|
66
|
+
description?: string;
|
|
67
|
+
ageRange?: string;
|
|
68
|
+
}): "dyslexia" | "lowVision" | "elderly" | "noMeasuredDifference";
|
|
69
|
+
/**
|
|
70
|
+
* The registry id a reading rule reads. An elderly cue reads the built-in
|
|
71
|
+
* elderly-user's own entry (personaRate.elderly-user.reading, the fixation-model
|
|
72
|
+
* hypothesis), decided 2026-10-23 so a custom elderly persona reads as the
|
|
73
|
+
* built-in one does; the others their customRate.* entry.
|
|
74
|
+
*/
|
|
75
|
+
export declare function customReadingRateId(rule: ReturnType<typeof customReadingRule>): string;
|
|
76
|
+
/**
|
|
77
|
+
* A persona's silent reading rate for display, wpm: 238 x its registered
|
|
78
|
+
* reading share, rounded. For the humanBehavior.timing.readingSpeed a persona
|
|
79
|
+
* carries, which personas.ts sets at load and so cannot read through param()
|
|
80
|
+
* (model-provenance.ts imports the persona tables); tests hold it equal to the
|
|
81
|
+
* param() value.
|
|
82
|
+
*/
|
|
83
|
+
export declare function displayReadingWpm(rateId: string): number;
|
|
84
|
+
//# sourceMappingURL=persona-rates.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"persona-rates.d.ts","sourceRoot":"","sources":["../../../src/visual/provenance/persona-rates.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AACH,OAAO,KAAK,EAAE,eAAe,EAAoB,MAAM,wBAAwB,CAAC;AAuDhF,eAAO,MAAM,uBAAuB,EAAE,eAAe,EA0BpD,CAAC;AAOF,eAAO,MAAM,sBAAsB,EAAE,eAAe,EAWnD,CAAC;AAGF,qEAAqE;AACrE,wBAAgB,kBAAkB,CAAC,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,QAAQ,GAAG,SAAS,GAAG,sBAAsB,CAKjK;AAED,6FAA6F;AAC7F,wBAAgB,iBAAiB,CAAC,CAAC,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,UAAU,GAAG,WAAW,GAAG,SAAS,GAAG,sBAAsB,CAM9J;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,UAAU,CAAC,OAAO,iBAAiB,CAAC,GAAG,MAAM,CAEtF;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAExD"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { LAW_PROVENANCE } from "./laws.js";
|
|
2
|
+
import { PROFILE_PROVENANCE } from "./profiles.js";
|
|
3
|
+
import { isOlderAdult } from "../../persona-age.js";
|
|
4
|
+
const registered = (id) => {
|
|
5
|
+
const e = [...LAW_PROVENANCE, ...PROFILE_PROVENANCE].find((x) => x.id === id);
|
|
6
|
+
if (!e)
|
|
7
|
+
throw new Error(`persona-rates: ${id} is not registered`);
|
|
8
|
+
return e.value;
|
|
9
|
+
};
|
|
10
|
+
const ratio = (rate, control) => registered(rate) / registered(control);
|
|
11
|
+
/** The fixation model's per-word slowdown, as a rate share: the neurotypical profile's time over this profile's. */
|
|
12
|
+
const fixationRatio = (phonological, visualSpan) => {
|
|
13
|
+
const ms = (phon, span) => registered("profile.fixation.baseMs")
|
|
14
|
+
+ (1 - phon) * registered("profile.fixation.phonologicalMs")
|
|
15
|
+
+ (registered("profile.fixation.normalSpan") / span - 1) * registered("profile.fixation.spanMs");
|
|
16
|
+
return ms(registered("profile.reading.neurotypical.phonological"), registered("profile.reading.neurotypical.visualSpan")) / ms(phonological, visualSpan);
|
|
17
|
+
};
|
|
18
|
+
const entry = (persona, channel, value, status, source) => ({ id: `personaRate.${persona}.${channel}`, value, status, source });
|
|
19
|
+
const NO_DIFFERENCE_POINTING = "No measured difference: no source retrieved measures a mouse throughput for this persona's population (or the persona is a behavioural archetype with no population) that differs from typical, so it points at the reference rate, law.rate.pointing.reference (ratio 1, c = 0.5). It replaced an interpolation on 0.6 proceduralFluency + 0.4 patience, dispositions that no source maps to throughput. An ISO 9241-9 mouse study of the population the persona stands for would set it.";
|
|
20
|
+
const NO_DIFFERENCE_READING = "No measured difference: no source retrieved measures a silent reading rate for this persona's population (or the persona is a behavioural archetype with no population) that differs from typical, so it reads at the reference rate, law.reading.wpm (ratio 1, c = 0.5). It replaced the fixation model's interpolation on 0.6 textProcessing + 0.4 comprehension toward the dyslexic profile, which no source supports. A silent reading study of the population the persona stands for would set it.";
|
|
21
|
+
const POINTING_NO_DIFFERENCE = [
|
|
22
|
+
"power-user", "first-timer", "screen-reader-user", "impatient-user", "distracted-user", "careful-reader", "explorer",
|
|
23
|
+
"task-focused", "low-vision-magnified", "dyslexic-user", "deaf-user", "color-blind-deuteranopia", "autism-spectrum",
|
|
24
|
+
"intellectual-disability", "aphasia-receptive", "dyscalculia", "anxious-user", "confident-user", "emotional-user", "stoic-user",
|
|
25
|
+
];
|
|
26
|
+
const READING_NO_DIFFERENCE = [
|
|
27
|
+
"power-user", "first-timer", "mobile-user", "screen-reader-user", "impatient-user", "distracted-user", "careful-reader",
|
|
28
|
+
"explorer", "task-focused", "motor-impairment-tremor", "deaf-user", "color-blind-deuteranopia", "autism-spectrum",
|
|
29
|
+
"dyscalculia", "anxious-user", "confident-user", "emotional-user", "stoic-user",
|
|
30
|
+
];
|
|
31
|
+
const ELDERLY_POINTING = "The elderly pointing profile, profile.pointing.elderly.throughput (3.2 bits/s) against law.rate.pointing.reference (4.9). No measured ISO mouse throughput for adults 65+ was found; Chaparro et al. (1999) support the direction (\"older adults took longer to complete movements than younger adults\") but give no rate. An ISO 9241-9 mouse study of adults 65+ would set it.";
|
|
32
|
+
const FIXATION_KEPT = (who, inputs, ms, why) => `Today's fixation-model slowdown for ${who}, kept as a hypothesis: the text-independent per-word time at ${inputs} is ${ms}, against 270 ms for the neurotypical profile, so the persona reads at that share of the reference rate (law.reading.wpm). ${why} A silent reading rate of the population against matched controls would set or replace it.`;
|
|
33
|
+
// Stage C (21.0, research/stage-c-design.md 10.5): the cognitiveLoad text terms
|
|
34
|
+
// that charged these two personas' comprehension against text are retired, so
|
|
35
|
+
// their language deficit is priced here alone. The before and after are mean
|
|
36
|
+
// totalCTC on the reference set named, viewport and full_page.
|
|
37
|
+
const STAGE_C_SEARCH = " (also not by the one targeted PubMed search of 2026-10-23 for aphasia or intellectual disability with reading rate, reading speed or words per minute: 51 records; its one intellectual-disability record is of children, and an adult rate against controls appears in none)";
|
|
38
|
+
const STAGE_C_ONLY = (who, comprehension, viewport, fullPage) => `Since Stage C (21.0) this share is the only place ${who}'s language-comprehension deficit is priced: the cognitiveLoad text terms that charged it through comprehension (${comprehension}, a UI-convention trait, not reading) are retired. On ctc-reference-v2-2026-10-24 (514 pages) its mean totalCTC moved ${viewport} at the viewport and ${fullPage} at full_page.`;
|
|
39
|
+
/** intellectual-disability's reading share before 21.0 (270 / 338 ms per word), frozen: see its entry. */
|
|
40
|
+
const ID_READING_BEFORE_21 = 0.7988165680473372;
|
|
41
|
+
export const PERSONA_RATE_PROVENANCE = [
|
|
42
|
+
// ── Pointing ──
|
|
43
|
+
entry("motor-impairment-tremor", "pointing", ratio("law.rate.pointing.motionImpaired", "law.rate.pointing.motionImpairedControls"), "published", "Motion-impaired mouse users measured against able-bodied controls in the same study, ISO 9241-9: 1.77 / 4.88 bits/s (law.rate.pointing.motionImpaired, law.rate.pointing.motionImpairedControls). Keates, Hwang, Langdon, Clarkson & Robinson (2002), read in Soukoreff & MacKenzie (2004), IJHCS 61, Table 4: \"1.77 69 Mouse (motion impared [sic])\" and \"4.88 11 Mouse (able-bodied)\". The group is motion-impaired users in general, not essential tremor specifically, at a 69% error rate."),
|
|
44
|
+
entry("elderly-user", "pointing", ratio("profile.pointing.elderly.throughput", "law.rate.pointing.reference"), "hypothesis", ELDERLY_POINTING),
|
|
45
|
+
entry("elderly-low-vision", "pointing", ratio("profile.pointing.elderly.throughput", "law.rate.pointing.reference"), "hypothesis", ELDERLY_POINTING),
|
|
46
|
+
entry("cognitive-adhd", "pointing", 1, "hypothesis", "No measured difference, and no measured rate: no throughput for adults with ADHD was found, so the persona points at the reference rate (ratio 1). The 4.2 bits/s it carried cited Flapper, Houwen & Schoemaker (2006), Dev Med Child Neurol 48(3), 165-169: \"A group of 12 children with ADHD-DCD\", with no throughput, and a motor deficit there belongs to the coordination disorder. An ISO 9241-9 mouse study of adults with ADHD and no coordination disorder would set it."),
|
|
47
|
+
entry("mobile-user", "pointing", 3.444 / 4.9, "hypothesis", "Unchanged until touch is modelled: the 3.444 bits/s that getPointingProfile's interpolation gave the persona (0.6 x 0.6 proceduralFluency + 0.4 x 0.3 patience between 4.9 and 2.1) before the tremor anchor moved, as a share of 4.9. A mouse throughput is the wrong measure for a finger; MacKenzie (2015) reports touch throughput but no regression, so no touch path exists to set it from. A touch pointing model with a measured rate would replace it."),
|
|
48
|
+
...POINTING_NO_DIFFERENCE.map((p) => entry(p, "pointing", 1, "hypothesis", NO_DIFFERENCE_POINTING)),
|
|
49
|
+
// ── Reading ──
|
|
50
|
+
entry("dyslexic-user", "reading", ratio("law.rate.reading.dyslexiaAdults", "law.rate.reading.dyslexiaControls"), "published", "Students with dyslexia measured against controls in the same study, silent text reading: 184.63 / 243.64 wpm (law.rate.reading.dyslexiaAdults, law.rate.reading.dyslexiaControls). Callens, Tops & Brysbaert (2012), PLoS ONE 7(6), e38081, Table 5, row \"Silent text reading (Tekenbeet)\": \"a group of 100 Dutch-speaking students diagnosed with dyslexia with a control group of 100 students without learning disabilities\". Dutch text; higher-education students are the more able end of adult dyslexia. A second source agrees in direction and size: Franzen, Stark & Johnson (2021), Individuals with dyslexia use a different visual sampling strategy to read text, Scientific Reports 11, 6449, doi:10.1038/s41598-021-84945-9: \"a lower words per minute reading rate among readers with dyslexia (Median Dyslexia = 178.09, Median Control = 248.18\", 67 adults reading silently, a ratio of 0.718 against Callens' 0.758."),
|
|
51
|
+
...["low-vision-magnified", "elderly-low-vision"].map((p) => entry(p, "reading", ratio("law.rate.reading.lowVisionIntactFields", "law.reading.wpm"), "hypothesis", "Low vision with intact central fields, 130 wpm median peak (law.rate.reading.lowVisionIntactFields; Legge, Rubin, Pelli & Schleske 1985, Vision Research 25(2): \"peak reading rates for observers with intact central fields were at least 90 words/minute (median 130 words/minute)\"), against the reference 238 wpm. Both numbers are published; the ratio is not, because it crosses methods (a peak rate at the best character size on drifting text against a silent reading rate) and the same-method normal-vision rate was not retrieved. Intact fields rather than central-field loss (25 wpm) was decided for both low-vision personas. Legge et al.'s normal-vision peak rate on the same apparatus would set it.")),
|
|
52
|
+
entry("elderly-user", "reading", fixationRatio(0.65, 5), "hypothesis", FIXATION_KEPT("elderly-user", "the elderly reading profile (phonological 0.65, visualSpan 5)", "317 ms", "No silent-reading norm for adults 65+ was found; Brysbaert (2019) reports that the drop \"is not expected to occur before the age of 60–65\", with no rate. Custom personas cued elderly or 65+ read at this same entry (decided 2026-10-23).")),
|
|
53
|
+
entry("cognitive-adhd", "reading", fixationRatio(0.75, 6), "hypothesis", FIXATION_KEPT("cognitive-adhd", "its stated reading traits (phonologicalDecoding 0.75, visualSpan 6)", "288.3 ms", "No measured silent-reading rate for adults with ADHD was found.")),
|
|
54
|
+
entry("intellectual-disability", "reading", ID_READING_BEFORE_21, "hypothesis", `No adult reading rate found; the value is the pre-21.0 one, frozen as a number (decided 2026-10-23). Through 20.x it was the fixation model's slowdown at the profile getReadingProfile interpolated from comprehension 0.2 (phonological 0.44, visualSpan 5: 338 ms per word against the neurotypical profile's 270 ms, a share of 270 / 338). getReadingProfile no longer reads comprehension, a UI-convention trait, so the share is kept as it was rather than recomputed from a profile nothing now produces. No reading rate for adults with intellectual disability was retrieved${STAGE_C_SEARCH}. ${STAGE_C_ONLY("intellectual-disability", "0.2", "0.855 -> 0.643", "0.837 -> 0.661")} A silent reading rate of adults with mild intellectual disability against matched controls would set or replace it.`),
|
|
55
|
+
entry("aphasia-receptive", "reading", ratio("law.rate.reading.aphasiaControlsSeconds", "law.rate.reading.aphasiaReadingImpairedSeconds"), "published", "People with aphasia whose reading comprehension is impaired, measured against age-matched controls in the same study by the same method: 30 / 71 seconds for the same paragraph (law.rate.reading.aphasiaControlsSeconds, law.rate.reading.aphasiaReadingImpairedSeconds), a reading-rate share of 0.423, c = 0.297. Webster, Morris, Howard & Garraffa (2018), AJSLP 27(1S), 423-437. Found by the one targeted PubMed search of 2026-10-23 (aphasia or intellectual disability with reading rate, reading speed or words per minute; 51 records). The group is post-stroke aphasia whose comprehension accuracy fell below the controls' 5th percentile, the closest measured group to receptive aphasia; the study does not classify aphasia type. Those without a measured reading impairment took 55 seconds (share 0.545). Until 21.0 the share was the fixation model's 0.804, interpolated from comprehension 0.25, a UI-convention trait. Since Stage C this share is the only place the persona's language-comprehension deficit is priced: the cognitiveLoad text terms that charged it through comprehension are retired."),
|
|
56
|
+
...READING_NO_DIFFERENCE.map((p) => entry(p, "reading", 1, "hypothesis", NO_DIFFERENCE_READING)),
|
|
57
|
+
];
|
|
58
|
+
// ── Custom personas: one entry per rule ──
|
|
59
|
+
const custom = (rule, channel, value, status, source) => ({ id: `customRate.${rule}.${channel}`, value, status, source });
|
|
60
|
+
export const CUSTOM_RATE_PROVENANCE = [
|
|
61
|
+
custom("tremor", "pointing", ratio("law.rate.pointing.motionImpaired", "law.rate.pointing.motionImpairedControls"), "published", "A custom persona with the tremor flag (accessibilityTraits.tremor, which the creation tool also sets for motor, arthritis, dexterity and mobility words) or tremor or Parkinson in its name or description: the motion-impaired rate against its same-study controls, 1.77 / 4.88 bits/s (Keates et al. 2002, in Soukoreff & MacKenzie 2004, Table 4), as for motor-impairment-tremor."),
|
|
62
|
+
custom("elderly", "pointing", ratio("profile.pointing.elderly.throughput", "law.rate.pointing.reference"), "hypothesis", `A custom persona whose stated age is 65 or above (an age range, a stated age such as "70-year-old", or a phrase that states age such as elderly, older adult or senior citizen; src/persona-age.ts): the elderly profile, as for the built-in elderly personas. ${ELDERLY_POINTING}`),
|
|
63
|
+
custom("noMeasuredDifference", "pointing", 1, "hypothesis", `A custom persona with no tremor flag and no elderly cue. ${NO_DIFFERENCE_POINTING}`),
|
|
64
|
+
custom("dyslexia", "reading", ratio("law.rate.reading.dyslexiaAdults", "law.rate.reading.dyslexiaControls"), "published", "A custom persona with dyslexia in its name or description and no stated reading-profile values: students with dyslexia against same-study controls, 184.63 / 243.64 wpm (Callens, Tops & Brysbaert 2012, PLoS ONE 7(6), e38081, Table 5), as for dyslexic-user."),
|
|
65
|
+
custom("lowVision", "reading", ratio("law.rate.reading.lowVisionIntactFields", "law.reading.wpm"), "hypothesis", "A custom persona with low vision, magnification, visual impairment, partial sight, vision loss, macular degeneration or glaucoma in its name or description and no stated reading-profile values: low vision with intact central fields, 130 wpm median peak (Legge, Rubin, Pelli & Schleske 1985) against the reference 238 wpm, as for the built-in low-vision personas. The ratio crosses methods; Legge et al.'s normal-vision peak rate on the same apparatus would set it. \"Blind\" is not a low-vision word: a blind reader does not read print."),
|
|
66
|
+
custom("noMeasuredDifference", "reading", 1, "hypothesis", `A custom persona with no stated reading-profile values and no dyslexia or low-vision cue. ${NO_DIFFERENCE_READING}`),
|
|
67
|
+
];
|
|
68
|
+
const LOW_VISION_WORDS = /low.?vision|magnif|visual(ly)?.?impair|partial(ly)?.?sight|vision.?loss|macular|glaucoma/;
|
|
69
|
+
/** Which customRate.* pointing rule a custom persona falls under. */
|
|
70
|
+
export function customPointingRule(p) {
|
|
71
|
+
const text = `${p.name ?? ""} ${p.description ?? ""}`.toLowerCase();
|
|
72
|
+
if (p.tremor === true || /tremor|parkinson/.test(text))
|
|
73
|
+
return "tremor";
|
|
74
|
+
if (isOlderAdult(p))
|
|
75
|
+
return "elderly";
|
|
76
|
+
return "noMeasuredDifference";
|
|
77
|
+
}
|
|
78
|
+
/** Which reading rule a custom persona with no stated reading-profile values falls under. */
|
|
79
|
+
export function customReadingRule(p) {
|
|
80
|
+
const text = `${p.name ?? ""} ${p.description ?? ""}`.toLowerCase();
|
|
81
|
+
if (/dyslexi/.test(text))
|
|
82
|
+
return "dyslexia";
|
|
83
|
+
if (LOW_VISION_WORDS.test(text))
|
|
84
|
+
return "lowVision";
|
|
85
|
+
if (isOlderAdult(p))
|
|
86
|
+
return "elderly";
|
|
87
|
+
return "noMeasuredDifference";
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* The registry id a reading rule reads. An elderly cue reads the built-in
|
|
91
|
+
* elderly-user's own entry (personaRate.elderly-user.reading, the fixation-model
|
|
92
|
+
* hypothesis), decided 2026-10-23 so a custom elderly persona reads as the
|
|
93
|
+
* built-in one does; the others their customRate.* entry.
|
|
94
|
+
*/
|
|
95
|
+
export function customReadingRateId(rule) {
|
|
96
|
+
return rule === "elderly" ? "personaRate.elderly-user.reading" : `customRate.${rule}.reading`;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* A persona's silent reading rate for display, wpm: 238 x its registered
|
|
100
|
+
* reading share, rounded. For the humanBehavior.timing.readingSpeed a persona
|
|
101
|
+
* carries, which personas.ts sets at load and so cannot read through param()
|
|
102
|
+
* (model-provenance.ts imports the persona tables); tests hold it equal to the
|
|
103
|
+
* param() value.
|
|
104
|
+
*/
|
|
105
|
+
export function displayReadingWpm(rateId) {
|
|
106
|
+
return Math.round(registered("law.reading.wpm") * [...PERSONA_RATE_PROVENANCE, ...CUSTOM_RATE_PROVENANCE].find((e) => e.id === rateId).value);
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=persona-rates.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"persona-rates.js","sourceRoot":"","sources":["../../../src/visual/provenance/persona-rates.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provenance catalogue for the built-in personas' trait values
|
|
3
|
+
* (personas.ts: BUILTIN_PERSONAS, ACCESSIBILITY_PERSONAS, EMOTIONAL_PERSONAS).
|
|
4
|
+
* See ../model-provenance.ts for the statuses.
|
|
5
|
+
*
|
|
6
|
+
* CATALOGUED, NOT READ THROUGH param(). Every other provenance group is read
|
|
7
|
+
* by id at the point of use. These are not: the chain and the distance take a
|
|
8
|
+
* persona's traits from the persona object, and rewriting personas.ts to read
|
|
9
|
+
* each of its numbers by id would bury the profiles it exists to make
|
|
10
|
+
* readable. So the entries are built FROM the persona objects at module load.
|
|
11
|
+
* The value here is the value the tools run on and cannot drift from it; what
|
|
12
|
+
* the registry adds is the status and the source. No code reads a `persona.`
|
|
13
|
+
* id through param(), so a recording will not contain one, and a check for
|
|
14
|
+
* registered ids that are never read must leave this prefix out.
|
|
15
|
+
* tests/persona-provenance.test.ts fails if a numeric trait in personas.ts has
|
|
16
|
+
* no entry or two, if a value differs from the source text, or if a persona or
|
|
17
|
+
* trait name appears that this file has no population or measure for.
|
|
18
|
+
*
|
|
19
|
+
* Every value is a `hypothesis`. All but the norm-anchored ones (NORM_ANCHORS
|
|
20
|
+
* below) were set by hand on a scale that no instrument defines (0-1 for all
|
|
21
|
+
* but visualSpan and contrastSensitivity, which have units). For those,
|
|
22
|
+
* personas.ts cites research in three ways, and none of them is a
|
|
23
|
+
* measurement of a value:
|
|
24
|
+
* - construct references. trait-reference.ts names a source per trait
|
|
25
|
+
* (Bandura for selfEfficacy, the Brief Resilience Scale for resilience),
|
|
26
|
+
* and personas.ts tags values with the same names, e.g. "(Bandura)". These
|
|
27
|
+
* say what the scale means, not where a persona sits on it.
|
|
28
|
+
* - a finding cited beside one value, e.g. dyslexic-user.workingMemory cites
|
|
29
|
+
* de Jong 2006 and PMC3496727. That is evidence for the DIRECTION of the
|
|
30
|
+
* persona's difference from typical, not for the number. Each such entry
|
|
31
|
+
* names its citation and what it was cited for.
|
|
32
|
+
* - a persona-level research note, e.g. the tremor prevalence on
|
|
33
|
+
* motor-impairment-tremor. It supports the persona's design, not any trait
|
|
34
|
+
* value, and is named in each of that persona's entries.
|
|
35
|
+
* A norm-anchored value is the percentile a published population mean
|
|
36
|
+
* implies on a normed instrument (paper section 3.1.1); its entry names that
|
|
37
|
+
* source and its interval, and it stays a hypothesis because mapping the
|
|
38
|
+
* instrument onto the trait is cbrowser's choice.
|
|
39
|
+
*
|
|
40
|
+
* What would test a value: the measure named per trait, given to a sample of
|
|
41
|
+
* the persona's population, with a 0-1 value compared as that sample's mean
|
|
42
|
+
* percentile against a general-population norm in the direction of the
|
|
43
|
+
* scale's high end. The scale has no other anchor, so fixing that mapping is
|
|
44
|
+
* the first step of any test. Five built-in personas are behavioural
|
|
45
|
+
* archetypes (impatient-user, distracted-user, careful-reader, explorer,
|
|
46
|
+
* task-focused) with no population until a screening criterion defines one,
|
|
47
|
+
* and their entries say so.
|
|
48
|
+
*
|
|
49
|
+
* @copyright 2026 Alexandria Eden alexandria.shai.eden@gmail.com https://cbrowser.ai
|
|
50
|
+
* @license MIT
|
|
51
|
+
*/
|
|
52
|
+
import type { ProvenanceEntry } from "../model-provenance.js";
|
|
53
|
+
/** The persona tables this catalogue covers, by the name personas.ts exports them under. */
|
|
54
|
+
export declare const PERSONA_TABLES: {
|
|
55
|
+
BUILTIN_PERSONAS: Record<string, import("../../types.js").Persona>;
|
|
56
|
+
ACCESSIBILITY_PERSONAS: Record<string, import("../../types.js").AccessibilityPersona>;
|
|
57
|
+
EMOTIONAL_PERSONAS: Record<string, import("../../types.js").Persona>;
|
|
58
|
+
};
|
|
59
|
+
/** The two trait groups whose numeric values are catalogued. */
|
|
60
|
+
export declare const TRAIT_GROUPS: readonly ["cognitiveTraits", "accessibilityTraits"];
|
|
61
|
+
/**
|
|
62
|
+
* A value set to its norm-implied value (paper section 3.1.1): the
|
|
63
|
+
* percentile, in the instrument's typical reference, of the persona
|
|
64
|
+
* population's mean, Phi(z) with z = (population mean - reference mean) /
|
|
65
|
+
* reference SD. A cell is here only if the source's 95% interval excluded the
|
|
66
|
+
* old value and all three of these held: the instrument measures the trait as
|
|
67
|
+
* trait-reference.ts defines it, the sample's age matches the persona's, and
|
|
68
|
+
* the 95% CI was read in the source. Every cell
|
|
69
|
+
* considered, and why each other one did not qualify, is listed in
|
|
70
|
+
* research/persona-norms/applied.md.
|
|
71
|
+
*
|
|
72
|
+
* The status stays `hypothesis`. The source measured the population on its
|
|
73
|
+
* instrument; that the instrument measures this trait is cbrowser's mapping.
|
|
74
|
+
* personas.ts holds Phi(z) to two decimals, and the test recomputes it from z.
|
|
75
|
+
*/
|
|
76
|
+
export interface NormAnchor {
|
|
77
|
+
/** The source, as retrieved. */
|
|
78
|
+
cite: string;
|
|
79
|
+
/** Where the number is printed in the source, and the number as printed. */
|
|
80
|
+
reported: string;
|
|
81
|
+
/** Population minus reference in reference SDs, with the source's 95% CI. */
|
|
82
|
+
z: number;
|
|
83
|
+
zLo: number;
|
|
84
|
+
zHi: number;
|
|
85
|
+
/** The value before 21.0 and what personas.ts cited it to. */
|
|
86
|
+
replaced: string;
|
|
87
|
+
/** What the value does not settle about the source. */
|
|
88
|
+
note?: string;
|
|
89
|
+
}
|
|
90
|
+
/** Norm-anchored values, keyed `<persona>.<trait>`. */
|
|
91
|
+
export declare const NORM_ANCHORS: Record<string, NormAnchor>;
|
|
92
|
+
/** A persona as the catalogue sees it: only the two trait groups matter. */
|
|
93
|
+
type PersonaLike = {
|
|
94
|
+
cognitiveTraits?: object;
|
|
95
|
+
accessibilityTraits?: object;
|
|
96
|
+
};
|
|
97
|
+
export interface PersonaCatalogue {
|
|
98
|
+
entries: ProvenanceEntry[];
|
|
99
|
+
/** Ids of numeric traits that could not be described (unknown persona or trait name, or a duplicate). */
|
|
100
|
+
uncovered: string[];
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Build one entry per numeric trait value in the given persona tables. A value
|
|
104
|
+
* whose persona or trait name this file has no population or measure for is
|
|
105
|
+
* reported as uncovered instead of registered, so the test fails rather than
|
|
106
|
+
* the module.
|
|
107
|
+
*/
|
|
108
|
+
export declare function cataloguePersonaTraits(tables: Record<string, Record<string, PersonaLike>>): PersonaCatalogue;
|
|
109
|
+
export declare const PERSONA_PROVENANCE: ProvenanceEntry[];
|
|
110
|
+
/** Numeric traits in personas.ts this file cannot describe yet. Must be empty; the test says which. */
|
|
111
|
+
export declare const PERSONA_PROVENANCE_UNCOVERED: readonly string[];
|
|
112
|
+
/** The keys of the hand-written tables above, so the test can catch a stale one. */
|
|
113
|
+
export declare const PERSONA_PROVENANCE_KEYS: {
|
|
114
|
+
populations: string[];
|
|
115
|
+
notes: string[];
|
|
116
|
+
valueCitations: string[];
|
|
117
|
+
citedDirections: Record<string, "low" | "mid" | "high">;
|
|
118
|
+
normAnchors: string[];
|
|
119
|
+
measures: string[];
|
|
120
|
+
};
|
|
121
|
+
export {};
|
|
122
|
+
//# sourceMappingURL=personas.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"personas.d.ts","sourceRoot":"","sources":["../../../src/visual/provenance/personas.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AACH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AA2B9D,4FAA4F;AAC5F,eAAO,MAAM,cAAc;;;;CAAmE,CAAC;AAE/F,gEAAgE;AAChE,eAAO,MAAM,YAAY,qDAAsD,CAAC;AAyLhF;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,UAAU;IACzB,gCAAgC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,4EAA4E;IAC5E,QAAQ,EAAE,MAAM,CAAC;IACjB,6EAA6E;IAC7E,CAAC,EAAE,MAAM,CAAC;IACV,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,8DAA8D;IAC9D,QAAQ,EAAE,MAAM,CAAC;IACjB,uDAAuD;IACvD,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,uDAAuD;AACvD,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAmBnD,CAAC;AAEF,4EAA4E;AAC5E,KAAK,WAAW,GAAG;IAAE,eAAe,CAAC,EAAE,MAAM,CAAC;IAAC,mBAAmB,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAE9E,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,yGAAyG;IACzG,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AA8CD;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,GAAG,gBAAgB,CAuB5G;AAID,eAAO,MAAM,kBAAkB,EAAE,eAAe,EAAsB,CAAC;AAEvE,uGAAuG;AACvG,eAAO,MAAM,4BAA4B,EAAE,SAAS,MAAM,EAAwB,CAAC;AAEnF,oFAAoF;AACpF,eAAO,MAAM,uBAAuB;;;;qBAM7B,MAAM,CAAC,MAAM,EAAE,KAAK,GAAG,KAAK,GAAG,MAAM,CAAC;;;CAG5C,CAAC"}
|