cbrowser 18.78.0 → 18.80.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/analysis/accessibility-empathy.d.ts.map +1 -1
- package/dist/analysis/accessibility-empathy.js +395 -66
- package/dist/analysis/accessibility-empathy.js.map +1 -1
- package/dist/analysis/agent-ready-audit.d.ts.map +1 -1
- package/dist/analysis/agent-ready-audit.js +78 -0
- package/dist/analysis/agent-ready-audit.js.map +1 -1
- package/dist/analysis/page-understanding.d.ts +139 -1
- package/dist/analysis/page-understanding.d.ts.map +1 -1
- package/dist/analysis/page-understanding.js +179 -12
- package/dist/analysis/page-understanding.js.map +1 -1
- package/dist/artifact-store.d.ts +19 -5
- package/dist/artifact-store.d.ts.map +1 -1
- package/dist/artifact-store.js +41 -11
- package/dist/artifact-store.js.map +1 -1
- package/dist/browser.d.ts +9 -0
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +81 -5
- package/dist/browser.js.map +1 -1
- package/dist/cli.js +55 -10
- package/dist/cli.js.map +1 -1
- package/dist/cognitive/index.d.ts.map +1 -1
- package/dist/cognitive/index.js +3 -2
- package/dist/cognitive/index.js.map +1 -1
- package/dist/config.d.ts +57 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +234 -7
- package/dist/config.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/mcp-server-remote.d.ts.map +1 -1
- package/dist/mcp-server-remote.js +108 -4
- package/dist/mcp-server-remote.js.map +1 -1
- package/dist/mcp-server.d.ts.map +1 -1
- package/dist/mcp-server.js +62 -938
- package/dist/mcp-server.js.map +1 -1
- package/dist/mcp-tools/account-personas.d.ts +41 -0
- package/dist/mcp-tools/account-personas.d.ts.map +1 -0
- package/dist/mcp-tools/account-personas.js +98 -0
- package/dist/mcp-tools/account-personas.js.map +1 -0
- package/dist/mcp-tools/base/analysis-tools.d.ts.map +1 -1
- package/dist/mcp-tools/base/analysis-tools.js +12 -2
- package/dist/mcp-tools/base/analysis-tools.js.map +1 -1
- package/dist/mcp-tools/base/artifact-tools.d.ts +3 -0
- package/dist/mcp-tools/base/artifact-tools.d.ts.map +1 -0
- package/dist/mcp-tools/base/artifact-tools.js +78 -0
- package/dist/mcp-tools/base/artifact-tools.js.map +1 -0
- package/dist/mcp-tools/base/audit-tools.d.ts +11 -0
- package/dist/mcp-tools/base/audit-tools.d.ts.map +1 -1
- package/dist/mcp-tools/base/audit-tools.js +595 -340
- package/dist/mcp-tools/base/audit-tools.js.map +1 -1
- package/dist/mcp-tools/base/browser-management-tools.d.ts.map +1 -1
- package/dist/mcp-tools/base/browser-management-tools.js +18 -0
- package/dist/mcp-tools/base/browser-management-tools.js.map +1 -1
- package/dist/mcp-tools/base/bug-analysis-tools.d.ts.map +1 -1
- package/dist/mcp-tools/base/bug-analysis-tools.js +59 -3
- package/dist/mcp-tools/base/bug-analysis-tools.js.map +1 -1
- package/dist/mcp-tools/base/capture-tools.d.ts +37 -0
- package/dist/mcp-tools/base/capture-tools.d.ts.map +1 -1
- package/dist/mcp-tools/base/capture-tools.js +267 -6
- package/dist/mcp-tools/base/capture-tools.js.map +1 -1
- package/dist/mcp-tools/base/cognitive-tools.d.ts +12 -0
- package/dist/mcp-tools/base/cognitive-tools.d.ts.map +1 -1
- package/dist/mcp-tools/base/cognitive-tools.js +63 -15
- package/dist/mcp-tools/base/cognitive-tools.js.map +1 -1
- package/dist/mcp-tools/base/extraction-tools.d.ts.map +1 -1
- package/dist/mcp-tools/base/extraction-tools.js +33 -2
- package/dist/mcp-tools/base/extraction-tools.js.map +1 -1
- package/dist/mcp-tools/base/index.d.ts +2 -0
- package/dist/mcp-tools/base/index.d.ts.map +1 -1
- package/dist/mcp-tools/base/index.js +9 -0
- package/dist/mcp-tools/base/index.js.map +1 -1
- package/dist/mcp-tools/base/marketing-tools.js +3 -3
- package/dist/mcp-tools/base/marketing-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 +529 -40
- package/dist/mcp-tools/base/persona-comparison-tools.js.map +1 -1
- package/dist/mcp-tools/base/site-knowledge-tools.d.ts.map +1 -1
- package/dist/mcp-tools/base/site-knowledge-tools.js +36 -3
- package/dist/mcp-tools/base/site-knowledge-tools.js.map +1 -1
- package/dist/mcp-tools/base/values-tools.d.ts +113 -0
- package/dist/mcp-tools/base/values-tools.d.ts.map +1 -1
- package/dist/mcp-tools/base/values-tools.js +868 -78
- package/dist/mcp-tools/base/values-tools.js.map +1 -1
- package/dist/mcp-tools/base/visual-testing-tools.d.ts.map +1 -1
- package/dist/mcp-tools/base/visual-testing-tools.js +130 -10
- package/dist/mcp-tools/base/visual-testing-tools.js.map +1 -1
- package/dist/mcp-tools/index.d.ts +3 -1
- package/dist/mcp-tools/index.d.ts.map +1 -1
- package/dist/mcp-tools/index.js +3 -28
- package/dist/mcp-tools/index.js.map +1 -1
- package/dist/mcp-tools/persona-creation-tools.d.ts.map +1 -1
- package/dist/mcp-tools/persona-creation-tools.js +363 -20
- package/dist/mcp-tools/persona-creation-tools.js.map +1 -1
- package/dist/mcp-tools/persona-lifecycle-tools.d.ts +3 -0
- package/dist/mcp-tools/persona-lifecycle-tools.d.ts.map +1 -0
- package/dist/mcp-tools/persona-lifecycle-tools.js +406 -0
- package/dist/mcp-tools/persona-lifecycle-tools.js.map +1 -0
- package/dist/mcp-tools/screenshot-utils.d.ts.map +1 -1
- package/dist/mcp-tools/screenshot-utils.js +56 -10
- package/dist/mcp-tools/screenshot-utils.js.map +1 -1
- package/dist/mcp-tools/tier-gate.js +2 -2
- package/dist/mcp-tools/tier-gate.js.map +1 -1
- package/dist/mcp-tools/tool-categories.d.ts.map +1 -1
- package/dist/mcp-tools/tool-categories.js +4 -1
- package/dist/mcp-tools/tool-categories.js.map +1 -1
- package/dist/mcp-tools/ui-resources.d.ts +167 -0
- package/dist/mcp-tools/ui-resources.d.ts.map +1 -0
- package/dist/mcp-tools/ui-resources.js +707 -0
- package/dist/mcp-tools/ui-resources.js.map +1 -0
- package/dist/mcp-tools/widget-kit.d.ts +299 -0
- package/dist/mcp-tools/widget-kit.d.ts.map +1 -0
- package/dist/mcp-tools/widget-kit.js +2034 -0
- package/dist/mcp-tools/widget-kit.js.map +1 -0
- package/dist/mcp-ui-resources.d.ts.map +1 -1
- package/dist/mcp-ui-resources.js +14 -4
- package/dist/mcp-ui-resources.js.map +1 -1
- package/dist/persona-questionnaire.d.ts +69 -1
- package/dist/persona-questionnaire.d.ts.map +1 -1
- package/dist/persona-questionnaire.js +177 -76
- package/dist/persona-questionnaire.js.map +1 -1
- package/dist/persona-scope.d.ts +20 -0
- package/dist/persona-scope.d.ts.map +1 -0
- package/dist/persona-scope.js +59 -0
- package/dist/persona-scope.js.map +1 -0
- package/dist/personas.d.ts +51 -17
- package/dist/personas.d.ts.map +1 -1
- package/dist/personas.js +947 -286
- package/dist/personas.js.map +1 -1
- package/dist/recording/capture-player.d.ts +68 -0
- package/dist/recording/capture-player.d.ts.map +1 -0
- package/dist/recording/capture-player.js +298 -0
- package/dist/recording/capture-player.js.map +1 -0
- package/dist/recording/engine.d.ts +52 -0
- package/dist/recording/engine.d.ts.map +1 -1
- package/dist/recording/engine.js +241 -3
- package/dist/recording/engine.js.map +1 -1
- package/dist/recording/inline-player.d.ts +39 -0
- package/dist/recording/inline-player.d.ts.map +1 -0
- package/dist/recording/inline-player.js +272 -0
- package/dist/recording/inline-player.js.map +1 -0
- package/dist/recording/saliency-overlay.d.ts +133 -0
- package/dist/recording/saliency-overlay.d.ts.map +1 -0
- package/dist/recording/saliency-overlay.js +360 -0
- package/dist/recording/saliency-overlay.js.map +1 -0
- package/dist/recording/types.d.ts +32 -0
- package/dist/recording/types.d.ts.map +1 -1
- package/dist/recording/types.js +46 -0
- package/dist/recording/types.js.map +1 -1
- package/dist/site-model/manager.d.ts +20 -0
- package/dist/site-model/manager.d.ts.map +1 -1
- package/dist/site-model/manager.js +52 -0
- package/dist/site-model/manager.js.map +1 -1
- package/dist/trait-reference.d.ts +26 -2
- package/dist/trait-reference.d.ts.map +1 -1
- package/dist/trait-reference.js +129 -19
- package/dist/trait-reference.js.map +1 -1
- package/dist/types.d.ts +105 -18
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/url-resolution.d.ts +58 -0
- package/dist/url-resolution.d.ts.map +1 -0
- package/dist/url-resolution.js +143 -0
- package/dist/url-resolution.js.map +1 -0
- package/dist/values/big-five-inference.d.ts +121 -0
- package/dist/values/big-five-inference.d.ts.map +1 -0
- package/dist/values/big-five-inference.js +241 -0
- package/dist/values/big-five-inference.js.map +1 -0
- package/dist/values/big-five-values.d.ts +76 -0
- package/dist/values/big-five-values.d.ts.map +1 -0
- package/dist/values/big-five-values.js +152 -0
- package/dist/values/big-five-values.js.map +1 -0
- package/dist/values/index.d.ts +1 -1
- package/dist/values/index.d.ts.map +1 -1
- package/dist/values/index.js +1 -1
- package/dist/values/index.js.map +1 -1
- package/dist/values/persona-completeness.d.ts +91 -0
- package/dist/values/persona-completeness.d.ts.map +1 -0
- package/dist/values/persona-completeness.js +114 -0
- package/dist/values/persona-completeness.js.map +1 -0
- package/dist/values/persona-diff.d.ts +50 -0
- package/dist/values/persona-diff.d.ts.map +1 -0
- package/dist/values/persona-diff.js +126 -0
- package/dist/values/persona-diff.js.map +1 -0
- package/dist/values/persona-values.d.ts +16 -0
- package/dist/values/persona-values.d.ts.map +1 -1
- package/dist/values/persona-values.js +33 -0
- package/dist/values/persona-values.js.map +1 -1
- package/dist/values/schwartz-values.d.ts +9 -1
- package/dist/values/schwartz-values.d.ts.map +1 -1
- package/dist/values/schwartz-values.js +10 -2
- package/dist/values/schwartz-values.js.map +1 -1
- package/dist/values/value-mappings.d.ts +41 -2
- package/dist/values/value-mappings.d.ts.map +1 -1
- package/dist/values/value-mappings.js +65 -8
- package/dist/values/value-mappings.js.map +1 -1
- package/dist/visual/attention-quality.d.ts +27 -0
- package/dist/visual/attention-quality.d.ts.map +1 -1
- package/dist/visual/attention-quality.js +164 -2
- package/dist/visual/attention-quality.js.map +1 -1
- package/dist/visual/attention-transport.d.ts +41 -2
- package/dist/visual/attention-transport.d.ts.map +1 -1
- package/dist/visual/attention-transport.js +98 -26
- package/dist/visual/attention-transport.js.map +1 -1
- package/dist/visual/barrier-overlay-html.d.ts +10 -0
- package/dist/visual/barrier-overlay-html.d.ts.map +1 -1
- package/dist/visual/barrier-overlay-html.js.map +1 -1
- package/dist/visual/cognitive-models.d.ts +109 -13
- package/dist/visual/cognitive-models.d.ts.map +1 -1
- package/dist/visual/cognitive-models.js +166 -3
- package/dist/visual/cognitive-models.js.map +1 -1
- package/dist/visual/cognitive-transport-chain.d.ts +149 -5
- package/dist/visual/cognitive-transport-chain.d.ts.map +1 -1
- package/dist/visual/cognitive-transport-chain.js +558 -30
- package/dist/visual/cognitive-transport-chain.js.map +1 -1
- package/dist/visual/cognitive-transport.d.ts +45 -3
- package/dist/visual/cognitive-transport.d.ts.map +1 -1
- package/dist/visual/cognitive-transport.js +126 -12
- package/dist/visual/cognitive-transport.js.map +1 -1
- package/dist/visual/fixation-corpus.d.ts +52 -0
- package/dist/visual/fixation-corpus.d.ts.map +1 -1
- package/dist/visual/fixation-corpus.js +95 -0
- package/dist/visual/fixation-corpus.js.map +1 -1
- package/dist/visual/llm-relevance.d.ts +193 -0
- package/dist/visual/llm-relevance.d.ts.map +1 -0
- package/dist/visual/llm-relevance.js +480 -0
- package/dist/visual/llm-relevance.js.map +1 -0
- package/dist/visual/perceptual-transport.d.ts +60 -0
- package/dist/visual/perceptual-transport.d.ts.map +1 -1
- package/dist/visual/perceptual-transport.js +228 -19
- package/dist/visual/perceptual-transport.js.map +1 -1
- package/dist/visual/persona-context.d.ts +23 -0
- package/dist/visual/persona-context.d.ts.map +1 -0
- package/dist/visual/persona-context.js +44 -0
- package/dist/visual/persona-context.js.map +1 -0
- package/package.json +2 -1
package/dist/personas.js
CHANGED
|
@@ -14,11 +14,28 @@ import { join } from "path";
|
|
|
14
14
|
import { homedir } from "os";
|
|
15
15
|
import { applyTraitCorrelations } from "./persona-questionnaire.js";
|
|
16
16
|
import { AGENT_PERSONAS, isAgentPersona, getAgentPersona, listAgentPersonas, isAgentPersonaObject } from "./agent-personas.js";
|
|
17
|
+
import { scopedDataDir } from "./persona-scope.js";
|
|
18
|
+
import { TRAIT_DEFINITIONS, canonicalizeTraits } from "./trait-reference.js";
|
|
17
19
|
// ============================================================================
|
|
18
20
|
// Custom Personas Storage
|
|
19
21
|
// ============================================================================
|
|
20
22
|
const DATA_DIR = process.env.CBROWSER_DATA_DIR || join(homedir(), ".cbrowser");
|
|
21
|
-
|
|
23
|
+
/**
|
|
24
|
+
* Resolved per call, not once at module load.
|
|
25
|
+
*
|
|
26
|
+
* A hosted server process serves many accounts, so the directory cannot be a
|
|
27
|
+
* constant fixed when the file is imported. `scopedDataDir()` returns the
|
|
28
|
+
* account bound to the CURRENT request's async context, or undefined when
|
|
29
|
+
* nothing entered a scope — which is every CLI run, every stdio session and
|
|
30
|
+
* every local install, all of which keep the previous behaviour exactly.
|
|
31
|
+
*
|
|
32
|
+
* Deliberately NOT a module-level `let` reassigned per request: that is the
|
|
33
|
+
* shape that lets two overlapping requests read each other's accounts, and it
|
|
34
|
+
* is the shape this codebase already removed from the billing path. (2026-08-01)
|
|
35
|
+
*/
|
|
36
|
+
function personasDirFor() {
|
|
37
|
+
return join(scopedDataDir() ?? DATA_DIR, "personas");
|
|
38
|
+
}
|
|
22
39
|
// ============================================================================
|
|
23
40
|
// Runtime Persona Registry (for Enterprise extensions)
|
|
24
41
|
// ============================================================================
|
|
@@ -32,21 +49,34 @@ function ensurePersonasDir() {
|
|
|
32
49
|
if (!existsSync(DATA_DIR)) {
|
|
33
50
|
mkdirSync(DATA_DIR, { recursive: true });
|
|
34
51
|
}
|
|
35
|
-
if (!existsSync(
|
|
36
|
-
mkdirSync(
|
|
52
|
+
if (!existsSync(personasDirFor())) {
|
|
53
|
+
mkdirSync(personasDirFor(), { recursive: true });
|
|
37
54
|
}
|
|
38
55
|
}
|
|
39
56
|
/**
|
|
40
57
|
* Load all custom personas from disk.
|
|
41
58
|
*/
|
|
59
|
+
/**
|
|
60
|
+
* Normalise a persona read off disk: deprecated trait keys to canonical ones.
|
|
61
|
+
*
|
|
62
|
+
* Without this a persona saved before the mentalModelRigidity rename loads with
|
|
63
|
+
* a key nothing recognises, so that trait silently stops contributing.
|
|
64
|
+
*/
|
|
65
|
+
function normalizePersonaOnRead(p) {
|
|
66
|
+
const t = p?.cognitiveTraits;
|
|
67
|
+
if (!t)
|
|
68
|
+
return p;
|
|
69
|
+
const canon = canonicalizeTraits(t);
|
|
70
|
+
return canon === t ? p : { ...p, cognitiveTraits: canon };
|
|
71
|
+
}
|
|
42
72
|
export function loadCustomPersonas() {
|
|
43
73
|
ensurePersonasDir();
|
|
44
74
|
const personas = {};
|
|
45
75
|
try {
|
|
46
|
-
const files = readdirSync(
|
|
76
|
+
const files = readdirSync(personasDirFor()).filter(f => f.endsWith(".json") || f.endsWith(".yaml") || f.endsWith(".yml"));
|
|
47
77
|
for (const file of files) {
|
|
48
78
|
try {
|
|
49
|
-
const content = readFileSync(join(
|
|
79
|
+
const content = readFileSync(join(personasDirFor(), file), "utf-8");
|
|
50
80
|
let persona;
|
|
51
81
|
if (file.endsWith(".json")) {
|
|
52
82
|
// Bare `as Persona` trusted arbitrary user-authored JSON to be complete.
|
|
@@ -54,7 +84,10 @@ export function loadCustomPersonas() {
|
|
|
54
84
|
// branch the same floor rather than letting a partial file reach
|
|
55
85
|
// getCognitiveProfile half-formed. (2026-07-28)
|
|
56
86
|
const parsed = JSON.parse(content);
|
|
57
|
-
|
|
87
|
+
// Deprecated trait keys resolved here, at the read boundary, so a
|
|
88
|
+
// persona saved before a rename keeps contributing instead of
|
|
89
|
+
// silently dropping the renamed trait.
|
|
90
|
+
persona = normalizePersonaOnRead({ ...parsed, behaviors: parsed.behaviors ?? {} });
|
|
58
91
|
}
|
|
59
92
|
else {
|
|
60
93
|
// Simple YAML parsing for persona files
|
|
@@ -84,11 +117,31 @@ export function loadCustomPersonas() {
|
|
|
84
117
|
/**
|
|
85
118
|
* Save a custom persona to disk.
|
|
86
119
|
*/
|
|
120
|
+
/**
|
|
121
|
+
* Remove run-scoped values a persona record must not carry.
|
|
122
|
+
*
|
|
123
|
+
* `siteFamiliarity` is a persona-SITE pair, not a disposition, so a stored one
|
|
124
|
+
* is always answering "familiar with which site?" about a site nobody named.
|
|
125
|
+
* Worse, the persona builder merged it over the caller's per-run parameter, so
|
|
126
|
+
* the tool discarded the input while reporting that it had applied it.
|
|
127
|
+
*
|
|
128
|
+
* Stripping on the way to disk rather than trusting every caller: this is the
|
|
129
|
+
* single chokepoint every custom persona passes through, and a rule enforced at
|
|
130
|
+
* one write is worth more than the same rule written in six call sites.
|
|
131
|
+
* (2026-08-02)
|
|
132
|
+
*/
|
|
133
|
+
export function stripStoredFamiliarity(persona) {
|
|
134
|
+
if (persona?.cognitiveTraits && "siteFamiliarity" in persona.cognitiveTraits) {
|
|
135
|
+
const { siteFamiliarity: _dropped, ...rest } = persona.cognitiveTraits;
|
|
136
|
+
return { ...persona, cognitiveTraits: rest };
|
|
137
|
+
}
|
|
138
|
+
return persona;
|
|
139
|
+
}
|
|
87
140
|
export function saveCustomPersona(persona) {
|
|
88
141
|
ensurePersonasDir();
|
|
89
142
|
const filename = `${persona.name.toLowerCase().replace(/[^a-z0-9-]/g, "-")}.json`;
|
|
90
|
-
const filepath = join(
|
|
91
|
-
writeFileSync(filepath, JSON.stringify(persona, null, 2));
|
|
143
|
+
const filepath = join(personasDirFor(), filename);
|
|
144
|
+
writeFileSync(filepath, JSON.stringify(stripStoredFamiliarity(persona), null, 2));
|
|
92
145
|
return filepath;
|
|
93
146
|
}
|
|
94
147
|
/**
|
|
@@ -103,7 +156,7 @@ export function deleteCustomPersona(name) {
|
|
|
103
156
|
const baseName = name.toLowerCase().replace(/[^a-z0-9-]/g, "-");
|
|
104
157
|
const extensions = [".json", ".yaml", ".yml"];
|
|
105
158
|
for (const ext of extensions) {
|
|
106
|
-
const filepath = join(
|
|
159
|
+
const filepath = join(personasDirFor(), `${baseName}${ext}`);
|
|
107
160
|
try {
|
|
108
161
|
if (existsSync(filepath)) {
|
|
109
162
|
unlinkSync(filepath);
|
|
@@ -560,7 +613,7 @@ function generateCognitiveTraitsFromDescription(descLower, techLevel, isImpatien
|
|
|
560
613
|
let emotionalContagion = 0.5;
|
|
561
614
|
let fearOfMissingOut = 0.5;
|
|
562
615
|
let socialProofSensitivity = 0.5;
|
|
563
|
-
let
|
|
616
|
+
let mentalModelFlexibility = 0.5;
|
|
564
617
|
// Adjust new traits by tech level
|
|
565
618
|
if (techLevel === "expert") {
|
|
566
619
|
informationForaging = 0.9; // Experts follow scent efficiently
|
|
@@ -575,7 +628,7 @@ function generateCognitiveTraitsFromDescription(descLower, techLevel, isImpatien
|
|
|
575
628
|
emotionalContagion = 0.2; // Mood-stable
|
|
576
629
|
fearOfMissingOut = 0.2; // Not swayed by urgency
|
|
577
630
|
socialProofSensitivity = 0.3; // Evaluate on merits
|
|
578
|
-
|
|
631
|
+
mentalModelFlexibility = 0.8; // Adapt to new patterns
|
|
579
632
|
}
|
|
580
633
|
else if (techLevel === "beginner") {
|
|
581
634
|
informationForaging = 0.3; // Exhaustive search
|
|
@@ -590,7 +643,7 @@ function generateCognitiveTraitsFromDescription(descLower, techLevel, isImpatien
|
|
|
590
643
|
emotionalContagion = 0.7; // Mood influenced by UI
|
|
591
644
|
fearOfMissingOut = 0.7; // Susceptible to urgency
|
|
592
645
|
socialProofSensitivity = 0.8; // Rely on reviews
|
|
593
|
-
|
|
646
|
+
mentalModelFlexibility = 0.3; // Struggle with new patterns
|
|
594
647
|
}
|
|
595
648
|
// Adjust for impatience
|
|
596
649
|
if (isImpatient) {
|
|
@@ -615,7 +668,7 @@ function generateCognitiveTraitsFromDescription(descLower, techLevel, isImpatien
|
|
|
615
668
|
proceduralFluency = Math.min(proceduralFluency, 0.35); // Struggle with sequences
|
|
616
669
|
transferLearning = Math.min(transferLearning, 0.25); // Each UI novel
|
|
617
670
|
authoritySensitivity = Math.max(authoritySensitivity, 0.7); // Trust authority
|
|
618
|
-
|
|
671
|
+
mentalModelFlexibility = Math.min(mentalModelFlexibility, 0.2); // Rigid mental models
|
|
619
672
|
}
|
|
620
673
|
// Adjust for vision issues (screen reader users)
|
|
621
674
|
if (hasVisionIssues) {
|
|
@@ -647,7 +700,7 @@ function generateCognitiveTraitsFromDescription(descLower, techLevel, isImpatien
|
|
|
647
700
|
emotionalContagion,
|
|
648
701
|
fearOfMissingOut,
|
|
649
702
|
socialProofSensitivity,
|
|
650
|
-
|
|
703
|
+
mentalModelFlexibility,
|
|
651
704
|
};
|
|
652
705
|
}
|
|
653
706
|
/**
|
|
@@ -691,8 +744,7 @@ export function createCognitivePersona(name, description, traits, options = {})
|
|
|
691
744
|
emotionalContagion: traits.emotionalContagion ?? basePersona.cognitiveTraits?.emotionalContagion ?? 0.5,
|
|
692
745
|
fearOfMissingOut: traits.fearOfMissingOut ?? basePersona.cognitiveTraits?.fearOfMissingOut ?? 0.5,
|
|
693
746
|
socialProofSensitivity: traits.socialProofSensitivity ?? basePersona.cognitiveTraits?.socialProofSensitivity ?? 0.5,
|
|
694
|
-
|
|
695
|
-
siteFamiliarity: traits.siteFamiliarity ?? basePersona.cognitiveTraits?.siteFamiliarity ?? 0.5,
|
|
747
|
+
mentalModelFlexibility: traits.mentalModelFlexibility ?? basePersona.cognitiveTraits?.mentalModelFlexibility ?? 0.5,
|
|
696
748
|
};
|
|
697
749
|
// Backstop for the failure mode above. The enumeration is kept because it
|
|
698
750
|
// documents each trait's fallback, but a hand-written list silently drops
|
|
@@ -738,7 +790,14 @@ export function createCognitivePersona(name, description, traits, options = {})
|
|
|
738
790
|
export function getCognitiveProfile(persona) {
|
|
739
791
|
// Derive attention pattern from humanBehavior.attention.pattern or behaviors
|
|
740
792
|
let attentionPattern = "f-pattern";
|
|
793
|
+
let attentionPatternSource = "default";
|
|
794
|
+
let attentionPatternMargin;
|
|
795
|
+
let attentionPatternConflict;
|
|
796
|
+
let techLevel;
|
|
797
|
+
let techLevelSource = "derived";
|
|
798
|
+
let techLevelConflict;
|
|
741
799
|
if (persona.humanBehavior?.attention?.pattern) {
|
|
800
|
+
attentionPatternSource = "declared";
|
|
742
801
|
const pattern = persona.humanBehavior.attention.pattern;
|
|
743
802
|
if (pattern === "skim")
|
|
744
803
|
attentionPattern = "skim";
|
|
@@ -758,17 +817,41 @@ export function getCognitiveProfile(persona) {
|
|
|
758
817
|
// it. (2026-07-28)
|
|
759
818
|
if (persona.behaviors?.attentionPattern) {
|
|
760
819
|
attentionPattern = persona.behaviors.attentionPattern;
|
|
820
|
+
attentionPatternSource = "declared";
|
|
761
821
|
}
|
|
822
|
+
const declaredAttentionPattern = attentionPatternSource === "declared" ? attentionPattern : undefined;
|
|
762
823
|
// Derive decision style from traits
|
|
763
824
|
let decisionStyle = "cautious";
|
|
825
|
+
let decisionStyleSource = "default";
|
|
826
|
+
let decisionStyleMargin;
|
|
827
|
+
let decisionStyleConfidence;
|
|
828
|
+
let decisionStyleRunnerUp;
|
|
829
|
+
let scoresTop;
|
|
764
830
|
const traits = persona.cognitiveTraits;
|
|
765
831
|
// v16.7.1: Validate trait completeness
|
|
766
832
|
if (traits) {
|
|
767
|
-
|
|
768
|
-
|
|
833
|
+
// Derived from the trait definitions rather than hardcoded. This was the
|
|
834
|
+
// literal 25 while the model had 26, so a persona missing exactly one trait
|
|
835
|
+
// counted as complete and the warning could never fire for it. A count that
|
|
836
|
+
// has to be updated by hand in step with a table is a count that will drift
|
|
837
|
+
// from it -- this file, mcp-server.ts, cognitive/index.ts, widget-kit.ts and
|
|
838
|
+
// cognitive-transport.ts had all drifted to 25 by 2026-08-01.
|
|
839
|
+
// Run-scoped and runtime-derived dimensions are excluded from the count.
|
|
840
|
+
//
|
|
841
|
+
// siteFamiliarity is deliberately not stored on personas (it is a
|
|
842
|
+
// persona-SITE pair supplied per run), and readingCapacity/motorCapacity/
|
|
843
|
+
// sustainedAttention are injected at analysis time -- the first two from the
|
|
844
|
+
// formal models, the third resolved from accessibilityTraits.attentionSpan.
|
|
845
|
+
// Counting them as "missing" made every persona in the roster warn on every
|
|
846
|
+
// load, which turns a real signal -- a persona that genuinely skipped traits
|
|
847
|
+
// -- into noise nobody reads. (2026-08-02)
|
|
848
|
+
const RUNTIME_SCOPED = new Set(["siteFamiliarity", "readingCapacity", "motorCapacity", "sustainedAttention"]);
|
|
849
|
+
const expectedTraitCount = Object.keys(TRAIT_DEFINITIONS).filter((t) => !RUNTIME_SCOPED.has(t)).length;
|
|
850
|
+
const actualTraitCount = Object.keys(traits)
|
|
851
|
+
.filter((k) => !RUNTIME_SCOPED.has(k) && traits[k] !== undefined).length;
|
|
769
852
|
if (actualTraitCount < expectedTraitCount) {
|
|
770
853
|
console.warn(`[CBrowser] Persona "${persona.name}" has ${actualTraitCount}/${expectedTraitCount} traits. ` +
|
|
771
|
-
`Missing traits will use defaults. Consider regenerating the persona for full
|
|
854
|
+
`Missing traits will use defaults. Consider regenerating the persona for the full ${expectedTraitCount}-trait model.`);
|
|
772
855
|
}
|
|
773
856
|
}
|
|
774
857
|
if (traits) {
|
|
@@ -777,24 +860,157 @@ export function getCognitiveProfile(persona) {
|
|
|
777
860
|
const riskTolerance = traits.riskTolerance ?? 0.5;
|
|
778
861
|
const comprehension = traits.comprehension ?? 0.5;
|
|
779
862
|
const readingTendency = traits.readingTendency ?? 0.5;
|
|
780
|
-
|
|
781
|
-
|
|
863
|
+
// Scored, not branched.
|
|
864
|
+
//
|
|
865
|
+
// An if/else chain is partial by construction: it answers only for the
|
|
866
|
+
// trait combinations someone thought to write a condition for, and every
|
|
867
|
+
// combination nobody covered silently inherits the initial literal. Six of
|
|
868
|
+
// twenty-one personas landed there -- first-timer among them -- reporting
|
|
869
|
+
// "cautious" because no branch matched, not because anything about them is
|
|
870
|
+
// cautious. Adding more branches moves the gap rather than closing it.
|
|
871
|
+
//
|
|
872
|
+
// Every style is scored from the trait vector and the highest wins, so a
|
|
873
|
+
// style is always chosen on evidence and the derivation is total: there is
|
|
874
|
+
// no combination left with no answer. (2026-07-31)
|
|
875
|
+
const t = (k, d = 0.5) => {
|
|
876
|
+
const v = traits[k];
|
|
877
|
+
return typeof v === "number" ? v : d;
|
|
878
|
+
};
|
|
879
|
+
const mean = (...xs) => xs.reduce((a, b) => a + b, 0) / xs.length;
|
|
880
|
+
const patienceV = t("patience");
|
|
881
|
+
const riskV = t("riskTolerance");
|
|
882
|
+
const satisficeV = t("satisficing");
|
|
883
|
+
const readingV = t("readingTendency");
|
|
884
|
+
const scores = [
|
|
885
|
+
// Acts before evaluating: tolerant of risk, short on patience, unplanned,
|
|
886
|
+
// and content with the first adequate option. Satisficing belongs here --
|
|
887
|
+
// without it someone with riskTolerance 0.8 and satisficing 0.25 scored
|
|
888
|
+
// impulsive, when refusing to settle is the opposite of impulsive.
|
|
889
|
+
["impulsive", mean(riskV, 1 - patienceV, 1 - t("metacognitivePlanning"), satisficeV)],
|
|
890
|
+
// Knows the pattern and takes the shortest path that works.
|
|
891
|
+
["efficient", mean(t("comprehension"), t("proceduralFluency"), satisficeV, 1 - readingV)],
|
|
892
|
+
// Checks before committing, and does not extend trust by default.
|
|
893
|
+
["cautious", mean(1 - riskV, 1 - t("trustCalibration"), patienceV)],
|
|
894
|
+
// Reads, plans, and refuses to settle for the first adequate option.
|
|
895
|
+
["deliberate", mean(readingV, patienceV, 1 - satisficeV, t("metacognitivePlanning"))],
|
|
896
|
+
];
|
|
897
|
+
// Only reachable on a touch device, where it describes the input mode
|
|
898
|
+
// rather than the disposition.
|
|
899
|
+
if (persona.demographics.device === "mobile") {
|
|
900
|
+
// Weighted to win on mobile unless the trait evidence clearly says
|
|
901
|
+
// otherwise. Device was previously a terminal branch, so every mobile
|
|
902
|
+
// persona was quick-tap; letting it compete unweighted relabelled all of
|
|
903
|
+
// them at once, which is a bigger claim than closing a coverage gap
|
|
904
|
+
// should be making.
|
|
905
|
+
scores.push(["quick-tap", mean(1 - patienceV, satisficeV, riskV) + 0.2]);
|
|
782
906
|
}
|
|
783
|
-
|
|
784
|
-
|
|
907
|
+
scores.sort((a, b) => b[1] - a[1]);
|
|
908
|
+
decisionStyle = scores[0][0];
|
|
909
|
+
scoresTop = scores[0][0];
|
|
910
|
+
decisionStyleSource = "derived";
|
|
911
|
+
// A near-tie is a weak reading, and saying so beats presenting the winner
|
|
912
|
+
// as though it were clear.
|
|
913
|
+
decisionStyleMargin = Math.round((scores[0][1] - scores[1][1]) * 100) / 100;
|
|
914
|
+
// ...but exposing the margin was not enough on its own.
|
|
915
|
+
//
|
|
916
|
+
// The style STRING carried identical authority at a margin of 0.03 as at
|
|
917
|
+
// 0.90, and a consumer reading only `decisionStyle` -- which is most of
|
|
918
|
+
// them -- got a coin flip presented as a finding. A number nobody is
|
|
919
|
+
// required to look at does not qualify the claim sitting next to it.
|
|
920
|
+
//
|
|
921
|
+
// Below 0.05 the two top styles are indistinguishable given the precision of
|
|
922
|
+
// the inputs, so the label is withheld rather than guessed and the runner-up
|
|
923
|
+
// is named so the tie is inspectable. (2026-08-02)
|
|
924
|
+
decisionStyleConfidence = decisionStyleMargin >= 0.20 ? "clear"
|
|
925
|
+
: decisionStyleMargin >= 0.05 ? "weak"
|
|
926
|
+
: "indistinguishable";
|
|
927
|
+
if (decisionStyleConfidence === "indistinguishable") {
|
|
928
|
+
decisionStyleRunnerUp = scores[1][0];
|
|
785
929
|
}
|
|
786
|
-
|
|
787
|
-
|
|
930
|
+
// Tech level, derived rather than trusted.
|
|
931
|
+
//
|
|
932
|
+
// demographics.tech_level is a creation-time literal that nothing ever
|
|
933
|
+
// revisits, and the default is "intermediate". Ten of twenty-one personas
|
|
934
|
+
// carried exactly that string while their fluency traits ranged from 0.28
|
|
935
|
+
// to 0.85 -- which is not ten independent judgements, it is one unset
|
|
936
|
+
// default. It is read by persona-comparison, so it affects output rather
|
|
937
|
+
// than only display.
|
|
938
|
+
//
|
|
939
|
+
// The stored value is left alone; someone may have meant it. The derived
|
|
940
|
+
// one is reported alongside, and a disagreement is named. (2026-08-01)
|
|
941
|
+
const fluency = mean(t("proceduralFluency"), t("transferLearning"), t("comprehension"));
|
|
942
|
+
const derivedTech = fluency >= 0.75 ? "expert" : fluency >= 0.5 ? "intermediate" : "beginner";
|
|
943
|
+
const declaredTech = persona.demographics?.tech_level;
|
|
944
|
+
techLevel = declaredTech ?? derivedTech;
|
|
945
|
+
techLevelSource = declaredTech ? "declared" : "derived";
|
|
946
|
+
if (declaredTech && declaredTech !== derivedTech) {
|
|
947
|
+
techLevelConflict =
|
|
948
|
+
`demographics.tech_level is "${declaredTech}", but this persona's fluency traits average ${Math.round(fluency * 100) / 100}, `
|
|
949
|
+
+ `which reads as "${derivedTech}" (proceduralFluency ${t("proceduralFluency")}, transferLearning ${t("transferLearning")}, comprehension ${t("comprehension")}). `
|
|
950
|
+
+ `The stored value is what persona-comparison uses.`;
|
|
788
951
|
}
|
|
789
|
-
|
|
790
|
-
|
|
952
|
+
// Attention pattern, derived the same way decisionStyle is.
|
|
953
|
+
//
|
|
954
|
+
// It was declared-or-default with no derivation at all, so a persona whose
|
|
955
|
+
// traits describe hard skimming could carry attentionPattern "thorough"
|
|
956
|
+
// and nothing anywhere would say the two disagreed -- and the declaration
|
|
957
|
+
// is what drives behaviour at runtime, so the contradiction changed how the
|
|
958
|
+
// persona read a page rather than merely how it was reported.
|
|
959
|
+
//
|
|
960
|
+
// Scored rather than branched, for the reason decisionStyle is: a branch
|
|
961
|
+
// chain answers only for combinations someone wrote a condition for, and
|
|
962
|
+
// everything else silently inherits the initial literal. Only the patterns
|
|
963
|
+
// the trait vector can actually speak to are scored. `sequential` is a
|
|
964
|
+
// navigation MODE (screen reader, tab order) and `z-pattern` is a property
|
|
965
|
+
// of sparse layouts rather than of a person, so neither is inferred from
|
|
966
|
+
// disposition -- they stay declarable and are never guessed. (2026-08-01)
|
|
967
|
+
const attnScores = [
|
|
968
|
+
// Reads everything, slowly: high reading, patient, refuses to settle.
|
|
969
|
+
["thorough", mean(readingV, patienceV, 1 - satisficeV, t("comprehension"))],
|
|
970
|
+
// Big elements only: low reading, impatient, settles fast.
|
|
971
|
+
["skim", mean(1 - readingV, 1 - patienceV, satisficeV)],
|
|
972
|
+
// Straight to the expected place: knows the conventions, forages by
|
|
973
|
+
// scent, does not need to read to locate.
|
|
974
|
+
["targeted", mean(t("proceduralFluency"), t("informationForaging"), satisficeV, 1 - readingV)],
|
|
975
|
+
// Notices everything, follows what is interesting rather than a plan.
|
|
976
|
+
["exploratory", mean(t("curiosity"), 1 - t("metacognitivePlanning"), t("informationForaging"))],
|
|
977
|
+
// The web-reading default: middling on the axes that separate the others.
|
|
978
|
+
// Scored rather than used as a fallback literal so it has to WIN to be
|
|
979
|
+
// chosen, which is what stops it becoming the silent catch-all the old
|
|
980
|
+
// default was.
|
|
981
|
+
["f-pattern", mean(0.5 + (0.5 - Math.abs(readingV - 0.5)), 0.5 + (0.5 - Math.abs(patienceV - 0.5))) * 0.9],
|
|
982
|
+
];
|
|
983
|
+
attnScores.sort((a, b) => b[1] - a[1]);
|
|
984
|
+
const derivedAttentionPattern = attnScores[0][0];
|
|
985
|
+
attentionPatternMargin = Math.round((attnScores[0][1] - attnScores[1][1]) * 100) / 100;
|
|
986
|
+
if (declaredAttentionPattern === undefined) {
|
|
987
|
+
attentionPattern = derivedAttentionPattern;
|
|
988
|
+
attentionPatternSource = "derived";
|
|
791
989
|
}
|
|
792
|
-
else if (
|
|
793
|
-
|
|
990
|
+
else if (declaredAttentionPattern !== derivedAttentionPattern) {
|
|
991
|
+
// The declaration still WINS -- someone wrote it deliberately and it may
|
|
992
|
+
// encode something the traits cannot, like a screen reader's sequential
|
|
993
|
+
// pass. But a disagreement this size is reported rather than swallowed,
|
|
994
|
+
// because the runtime behaviour follows the declaration and the numbers
|
|
995
|
+
// say something else.
|
|
996
|
+
// A conflict is only as strong as the derivation behind it. When the
|
|
997
|
+
// top two derived patterns are themselves a near-tie, "the traits say X"
|
|
998
|
+
// overstates what the numbers support -- the honest claim is that the
|
|
999
|
+
// traits do not endorse the declaration, not that they pick a different
|
|
1000
|
+
// winner. Same rule the Maslow tie reporting follows.
|
|
1001
|
+
const decisive = (attentionPatternMargin ?? 0) > 0.05;
|
|
1002
|
+
attentionPatternConflict = decisive
|
|
1003
|
+
? `declared "${declaredAttentionPattern}", but this persona's traits score "${derivedAttentionPattern}" highest by ${attentionPatternMargin} `
|
|
1004
|
+
+ `(reading ${readingV}, patience ${patienceV}, satisficing ${satisficeV}). `
|
|
1005
|
+
+ `The declaration is in force at runtime; the trait vector disagrees with it.`
|
|
1006
|
+
: `declared "${declaredAttentionPattern}", which is not what the traits favour — though they do not clearly favour anything either `
|
|
1007
|
+
+ `("${derivedAttentionPattern}" leads by only ${attentionPatternMargin}). `
|
|
1008
|
+
+ `Read this as the declaration being unsupported rather than contradicted.`;
|
|
794
1009
|
}
|
|
795
1010
|
}
|
|
796
1011
|
if (persona.behaviors?.decisionStyle) {
|
|
797
1012
|
decisionStyle = persona.behaviors.decisionStyle;
|
|
1013
|
+
decisionStyleSource = "declared";
|
|
798
1014
|
}
|
|
799
1015
|
// v16.14.1: Merge traits with defaults to ensure complete CognitiveTraits
|
|
800
1016
|
// This handles both Persona (full traits) and AccessibilityPersona (partial traits)
|
|
@@ -826,13 +1042,44 @@ export function getCognitiveProfile(persona) {
|
|
|
826
1042
|
emotionalContagion: 0.5,
|
|
827
1043
|
fearOfMissingOut: 0.5,
|
|
828
1044
|
socialProofSensitivity: 0.5,
|
|
829
|
-
|
|
830
|
-
siteFamiliarity: 0.5,
|
|
1045
|
+
mentalModelFlexibility: 0.5,
|
|
831
1046
|
};
|
|
832
1047
|
return {
|
|
833
1048
|
traits: traits ? { ...defaultTraits, ...traits } : defaultTraits,
|
|
834
1049
|
attentionPattern,
|
|
835
|
-
|
|
1050
|
+
// NULL when suppressed, not omitted.
|
|
1051
|
+
//
|
|
1052
|
+
// Omitting the key left consumers unable to tell suppression from "never
|
|
1053
|
+
// computed", while decisionStyleSource still said "derived" -- claiming a
|
|
1054
|
+
// derivation for a value that was not there. An explicit null plus a
|
|
1055
|
+
// suppression flag and the threshold says what happened. (2026-08-02)
|
|
1056
|
+
decisionStyle: decisionStyleConfidence === "indistinguishable" ? null : decisionStyle,
|
|
1057
|
+
...(decisionStyleConfidence === "indistinguishable"
|
|
1058
|
+
? { decisionStyleSuppressed: true, decisionStyleThreshold: 0.05 }
|
|
1059
|
+
: {}),
|
|
1060
|
+
attentionPatternSource,
|
|
1061
|
+
attentionPatternMargin,
|
|
1062
|
+
attentionPatternConflict,
|
|
1063
|
+
techLevel,
|
|
1064
|
+
techLevelSource,
|
|
1065
|
+
techLevelConflict,
|
|
1066
|
+
// Reports SUPPRESSION rather than claiming a derivation whose result was
|
|
1067
|
+
// withheld. It said "derived" beside an absent decisionStyle.
|
|
1068
|
+
decisionStyleSource: decisionStyleConfidence === "indistinguishable" ? "suppressed" : decisionStyleSource,
|
|
1069
|
+
...(decisionStyleMargin !== undefined ? { decisionStyleMargin } : {}),
|
|
1070
|
+
...(decisionStyleConfidence ? { decisionStyleConfidence } : {}),
|
|
1071
|
+
// The LABEL is withheld at an indistinguishable margin, not just annotated.
|
|
1072
|
+
// Annotating it leaves the string in place for every consumer that reads
|
|
1073
|
+
// only `decisionStyle`, which is the failure this fixes. The candidate is
|
|
1074
|
+
// still available as decisionStyleRunnerUp plus the winner below, so
|
|
1075
|
+
// nothing is hidden -- it just stops being asserted.
|
|
1076
|
+
...(decisionStyleConfidence === "indistinguishable"
|
|
1077
|
+
? { decisionStyleCandidates: [scoresTop, decisionStyleRunnerUp].filter((x) => !!x) }
|
|
1078
|
+
: {}),
|
|
1079
|
+
...(decisionStyleRunnerUp ? { decisionStyleRunnerUp } : {}),
|
|
1080
|
+
...(decisionStyleConfidence === "indistinguishable"
|
|
1081
|
+
? { decisionStyleNote: `Withheld: the top two styles differ by ${decisionStyleMargin}, which is inside the noise of the inputs. Runner-up was ${decisionStyleRunnerUp}. A label at this margin is a coin flip wearing a finding's clothes.` }
|
|
1082
|
+
: {}),
|
|
836
1083
|
innerVoiceTemplate: persona.behaviors?.innerVoiceTemplate,
|
|
837
1084
|
};
|
|
838
1085
|
}
|
|
@@ -883,32 +1130,31 @@ export const BUILTIN_PERSONAS = {
|
|
|
883
1130
|
},
|
|
884
1131
|
cognitiveTraits: {
|
|
885
1132
|
patience: 0.3, // Low - expects things to work
|
|
886
|
-
riskTolerance: 0.
|
|
887
|
-
comprehension: 0.
|
|
1133
|
+
riskTolerance: 0.8, // High - clicks confidently
|
|
1134
|
+
comprehension: 0.9, // Expert - knows all conventions
|
|
888
1135
|
persistence: 0.4, // Low - switches approaches quickly
|
|
889
1136
|
curiosity: 0.2, // Low - stays focused on goal
|
|
890
1137
|
workingMemory: 0.9, // High - never repeats attempts
|
|
891
|
-
readingTendency: 0.
|
|
892
|
-
resilience: 0.
|
|
1138
|
+
readingTendency: 0.2, // Low - scans for shortcuts
|
|
1139
|
+
resilience: 0.8, // High - shrugs off errors quickly (BRS)
|
|
893
1140
|
selfEfficacy: 0.9, // High - trusts own expertise (Bandura)
|
|
894
|
-
satisficing: 0.
|
|
1141
|
+
satisficing: 0.4, // Low - knows quality, seeks optimal (Simon)
|
|
895
1142
|
trustCalibration: 0.7, // High - trusts tech but verifies (Fogg)
|
|
896
|
-
interruptRecovery: 0.
|
|
1143
|
+
interruptRecovery: 0.9, // High - uses env cues, resumes fast (Mark)
|
|
897
1144
|
// New traits (v15.0.0)
|
|
898
1145
|
informationForaging: 0.9, // High - follows scent efficiently
|
|
899
|
-
changeBlindness: 0.
|
|
1146
|
+
changeBlindness: 0.3, // Low - notices UI changes
|
|
900
1147
|
anchoringBias: 0.3, // Low - compares options freely
|
|
901
1148
|
timeHorizon: 0.3, // Long-term - invests in learning
|
|
902
1149
|
attributionStyle: 0.2, // Blames system - "this is broken"
|
|
903
1150
|
metacognitivePlanning: 0.8, // High - plans before acting
|
|
904
1151
|
proceduralFluency: 0.9, // High - follows procedures easily
|
|
905
|
-
transferLearning: 0.
|
|
1152
|
+
transferLearning: 0.9, // High - applies knowledge across UIs
|
|
906
1153
|
authoritySensitivity: 0.3, // Low - questions authority, verifies
|
|
907
|
-
emotionalContagion: 0.
|
|
1154
|
+
emotionalContagion: 0.3, // Low - mood-stable
|
|
908
1155
|
fearOfMissingOut: 0.2, // Low - not swayed by urgency
|
|
909
1156
|
socialProofSensitivity: 0.3, // Low - evaluates on merits
|
|
910
|
-
|
|
911
|
-
siteFamiliarity: 0.9, // Very high - daily user, knows everything
|
|
1157
|
+
mentalModelFlexibility: 0.8, // High - adapts to new patterns
|
|
912
1158
|
},
|
|
913
1159
|
context: {
|
|
914
1160
|
viewport: [1920, 1080],
|
|
@@ -962,33 +1208,32 @@ export const BUILTIN_PERSONAS = {
|
|
|
962
1208
|
},
|
|
963
1209
|
},
|
|
964
1210
|
cognitiveTraits: {
|
|
965
|
-
patience: 0.
|
|
1211
|
+
patience: 0.7, // Medium - willing to learn
|
|
966
1212
|
riskTolerance: 0.3, // Low - hesitates before clicking
|
|
967
1213
|
comprehension: 0.3, // Low - doesn't know conventions
|
|
968
1214
|
persistence: 0.5, // Medium - tries a few times
|
|
969
|
-
curiosity: 0.
|
|
1215
|
+
curiosity: 0.9, // High - explores the interface
|
|
970
1216
|
workingMemory: 0.4, // Medium - might repeat mistakes
|
|
971
|
-
readingTendency: 0.
|
|
1217
|
+
readingTendency: 0.6, // High - reads tooltips and help
|
|
972
1218
|
resilience: 0.4, // Low-medium - new users get discouraged (BRS)
|
|
973
1219
|
selfEfficacy: 0.4, // Low - uncertain of abilities (Bandura)
|
|
974
|
-
satisficing: 0.
|
|
1220
|
+
satisficing: 0.6, // Medium - unsure what's "good enough" (Simon)
|
|
975
1221
|
trustCalibration: 0.4, // Low - skeptical, unsure what to trust (Fogg)
|
|
976
|
-
interruptRecovery: 0.
|
|
1222
|
+
interruptRecovery: 0.4, // Low - easily loses place, restarts (Mark)
|
|
977
1223
|
// New traits (v15.0.0)
|
|
978
|
-
informationForaging: 0.
|
|
1224
|
+
informationForaging: 0.4, // Low - exhaustive search, clicks everything
|
|
979
1225
|
changeBlindness: 0.6, // High - misses peripheral changes
|
|
980
1226
|
anchoringBias: 0.7, // High - anchored to first information
|
|
981
1227
|
timeHorizon: 0.7, // Short-term - wants quick results
|
|
982
1228
|
attributionStyle: 0.7, // Self-blaming - "I must be doing it wrong"
|
|
983
1229
|
metacognitivePlanning: 0.3, // Low - trial-and-error approach
|
|
984
|
-
proceduralFluency: 0.
|
|
1230
|
+
proceduralFluency: 0.2, // Low - struggles with multi-step flows
|
|
985
1231
|
transferLearning: 0.2, // Low - each interface feels new
|
|
986
|
-
authoritySensitivity: 0.
|
|
987
|
-
emotionalContagion: 0.
|
|
1232
|
+
authoritySensitivity: 0.7, // High - trusts official-looking cues
|
|
1233
|
+
emotionalContagion: 0.6, // High - influenced by UI tone
|
|
988
1234
|
fearOfMissingOut: 0.6, // Medium-high - susceptible to urgency
|
|
989
|
-
socialProofSensitivity: 0.
|
|
990
|
-
|
|
991
|
-
siteFamiliarity: 0.0, // Zero - brand new, never visited before
|
|
1235
|
+
socialProofSensitivity: 0.7, // High - relies heavily on reviews
|
|
1236
|
+
mentalModelFlexibility: 0.3, // Low - struggles when patterns break
|
|
992
1237
|
},
|
|
993
1238
|
context: {
|
|
994
1239
|
viewport: [1280, 800],
|
|
@@ -1036,33 +1281,32 @@ export const BUILTIN_PERSONAS = {
|
|
|
1036
1281
|
},
|
|
1037
1282
|
},
|
|
1038
1283
|
cognitiveTraits: {
|
|
1039
|
-
patience: 0.
|
|
1284
|
+
patience: 0.3, // Low - mobile = quick tasks
|
|
1040
1285
|
riskTolerance: 0.6, // Medium - taps somewhat freely
|
|
1041
1286
|
comprehension: 0.6, // Medium - knows mobile patterns
|
|
1042
|
-
persistence: 0.
|
|
1043
|
-
curiosity: 0.
|
|
1287
|
+
persistence: 0.4, // Low - gives up if fiddly
|
|
1288
|
+
curiosity: 0.4, // Low - wants to complete and go
|
|
1044
1289
|
workingMemory: 0.5, // Medium
|
|
1045
|
-
readingTendency: 0.
|
|
1290
|
+
readingTendency: 0.2, // Low - minimal reading on mobile
|
|
1046
1291
|
resilience: 0.5, // Medium - recovers if next try works (BRS)
|
|
1047
1292
|
selfEfficacy: 0.6, // Medium - comfortable in mobile context (Bandura)
|
|
1048
1293
|
satisficing: 0.8, // High - mobile context demands quick decisions (Simon)
|
|
1049
1294
|
trustCalibration: 0.6, // Medium - quick decisions, moderate trust (Fogg)
|
|
1050
|
-
interruptRecovery: 0.
|
|
1295
|
+
interruptRecovery: 0.5, // Low-Med - constant phone interruptions (Mark)
|
|
1051
1296
|
// New traits (v15.0.0)
|
|
1052
1297
|
informationForaging: 0.7, // High - efficient mobile navigation
|
|
1053
|
-
changeBlindness: 0.
|
|
1298
|
+
changeBlindness: 0.6, // Medium - small screen limits peripheral
|
|
1054
1299
|
anchoringBias: 0.5, // Medium
|
|
1055
1300
|
timeHorizon: 0.8, // Very short-term - mobile is quick tasks
|
|
1056
1301
|
attributionStyle: 0.4, // Medium - blames small screen/touch
|
|
1057
1302
|
metacognitivePlanning: 0.4, // Low-medium - quick decisions
|
|
1058
1303
|
proceduralFluency: 0.6, // Medium - knows mobile patterns
|
|
1059
|
-
transferLearning: 0.
|
|
1304
|
+
transferLearning: 0.6, // High - mobile UI conventions
|
|
1060
1305
|
authoritySensitivity: 0.5, // Medium
|
|
1061
1306
|
emotionalContagion: 0.5, // Medium
|
|
1062
|
-
fearOfMissingOut: 0.
|
|
1307
|
+
fearOfMissingOut: 0.6, // High - push notifications, urgency
|
|
1063
1308
|
socialProofSensitivity: 0.6, // Medium-high - app store ratings
|
|
1064
|
-
|
|
1065
|
-
siteFamiliarity: 0.4, // Low-medium - used desktop version before
|
|
1309
|
+
mentalModelFlexibility: 0.6, // Medium - adapts to mobile patterns
|
|
1066
1310
|
},
|
|
1067
1311
|
context: {
|
|
1068
1312
|
viewport: [375, 812], // iPhone X dimensions
|
|
@@ -1110,33 +1354,41 @@ export const BUILTIN_PERSONAS = {
|
|
|
1110
1354
|
},
|
|
1111
1355
|
},
|
|
1112
1356
|
cognitiveTraits: {
|
|
1113
|
-
patience: 0.
|
|
1114
|
-
|
|
1357
|
+
patience: 0.9, // High - used to slow navigation
|
|
1358
|
+
// 0.5 -> 0.2 (2026-08-02). Screen-reader navigation carries a real
|
|
1359
|
+
// disorientation cost: no visual context to recover from, high cognitive
|
|
1360
|
+
// load from remembering shortcuts and prior steps, and interface changes
|
|
1361
|
+
// that go unannounced. The documented behaviour is cautious exploration
|
|
1362
|
+
// to avoid that cost, which is the low end of this scale ('only clicks
|
|
1363
|
+
// obvious, labeled buttons') rather than the middle.
|
|
1364
|
+
// Sources: Information Wayfinding of Screen Reader Users, ASSETS 2024
|
|
1365
|
+
// (dl.acm.org/doi/fullHtml/10.1145/3663548.3688539); Context-Aware
|
|
1366
|
+
// Guidance for Screen Reader Users, CHI 2026 (10.1145/3772318.3790661).
|
|
1367
|
+
riskTolerance: 0.2, // Medium - careful but experienced
|
|
1115
1368
|
comprehension: 0.8, // High - expert at a11y patterns
|
|
1116
1369
|
persistence: 0.9, // High - determination required
|
|
1117
1370
|
curiosity: 0.2, // Low - structured navigation
|
|
1118
|
-
workingMemory: 0.
|
|
1119
|
-
readingTendency:
|
|
1371
|
+
workingMemory: 0.7, // High - mental model essential
|
|
1372
|
+
readingTendency: 0.9, // Full - ALL content is read aloud
|
|
1120
1373
|
resilience: 0.8, // High - experienced with setbacks (CD-RISC)
|
|
1121
|
-
selfEfficacy: 0.
|
|
1374
|
+
selfEfficacy: 0.7, // Medium - high in accessible sites, low otherwise (Bandura)
|
|
1122
1375
|
satisficing: 0.6, // Medium - relies on structured review content (Simon)
|
|
1123
|
-
trustCalibration: 0.
|
|
1124
|
-
interruptRecovery: 0.
|
|
1376
|
+
trustCalibration: 0.6, // Medium - cautious from past a11y failures (Fogg)
|
|
1377
|
+
interruptRecovery: 0.6, // High - strong mental model aids recovery (Mark)
|
|
1125
1378
|
// New traits (v15.0.0)
|
|
1126
|
-
informationForaging: 0.
|
|
1379
|
+
informationForaging: 0.6, // High - sequential but efficient with landmarks
|
|
1127
1380
|
changeBlindness: 0.3, // Low - ARIA live regions announce changes
|
|
1128
1381
|
anchoringBias: 0.4, // Medium - sequential exposure to info
|
|
1129
1382
|
timeHorizon: 0.3, // Long-term - patient, thorough
|
|
1130
1383
|
attributionStyle: 0.4, // Medium - blames inaccessible design
|
|
1131
|
-
metacognitivePlanning: 0.
|
|
1384
|
+
metacognitivePlanning: 0.7, // Very high - plans navigation carefully
|
|
1132
1385
|
proceduralFluency: 0.8, // High - follows heading structure
|
|
1133
|
-
transferLearning: 0.
|
|
1386
|
+
transferLearning: 0.7, // High - knows a11y patterns across sites
|
|
1134
1387
|
authoritySensitivity: 0.5, // Medium - verifies with screen reader
|
|
1135
1388
|
emotionalContagion: 0.3, // Low - focused on structure, not tone
|
|
1136
|
-
fearOfMissingOut: 0.
|
|
1389
|
+
fearOfMissingOut: 0.4, // Low - methodical, not impulsive
|
|
1137
1390
|
socialProofSensitivity: 0.5, // Medium - reviews are accessible info
|
|
1138
|
-
|
|
1139
|
-
siteFamiliarity: 0.3, // Low - has visited but forgets layout
|
|
1391
|
+
mentalModelFlexibility: 0.6, // Medium - adapts but needs time
|
|
1140
1392
|
},
|
|
1141
1393
|
context: {
|
|
1142
1394
|
viewport: [1280, 800],
|
|
@@ -1184,33 +1436,59 @@ export const BUILTIN_PERSONAS = {
|
|
|
1184
1436
|
},
|
|
1185
1437
|
},
|
|
1186
1438
|
cognitiveTraits: {
|
|
1187
|
-
patience: 0.
|
|
1188
|
-
riskTolerance: 0.
|
|
1439
|
+
patience: 0.8, // High - not in a rush
|
|
1440
|
+
riskTolerance: 0.2, // Very low - afraid of mistakes
|
|
1189
1441
|
comprehension: 0.2, // Low - unfamiliar with modern UI
|
|
1190
|
-
persistence: 0.
|
|
1191
|
-
curiosity: 0.
|
|
1192
|
-
workingMemory: 0.
|
|
1193
|
-
readingTendency: 0.
|
|
1442
|
+
persistence: 0.6, // High - determined but confused
|
|
1443
|
+
curiosity: 0.4, // Very low - just wants to finish
|
|
1444
|
+
workingMemory: 0.4, // Low - may forget steps
|
|
1445
|
+
readingTendency: 0.8, // High - reads everything carefully
|
|
1194
1446
|
resilience: 0.3, // Low - frustration lingers longer (BRS age-related)
|
|
1195
|
-
selfEfficacy: 0.
|
|
1196
|
-
satisficing: 0.
|
|
1447
|
+
selfEfficacy: 0.4, // Low - often blame themselves for tech issues (Bandura)
|
|
1448
|
+
satisficing: 0.6, // High - values simplicity over optimization (Simon)
|
|
1197
1449
|
trustCalibration: 0.25, // Very low - skeptical of online requests (Fogg)
|
|
1198
|
-
interruptRecovery: 0.
|
|
1450
|
+
interruptRecovery: 0.4, // Low - difficulty resuming, forgets context (Mark)
|
|
1199
1451
|
// New traits (v15.0.0)
|
|
1200
1452
|
informationForaging: 0.25, // Very low - exhaustive, uncertain search
|
|
1201
|
-
changeBlindness: 0.
|
|
1202
|
-
anchoringBias: 0.
|
|
1453
|
+
changeBlindness: 0.6, // High - misses UI updates and changes
|
|
1454
|
+
anchoringBias: 0.7, // High - sticks to first information
|
|
1203
1455
|
timeHorizon: 0.4, // Medium - patient but unsure of value
|
|
1204
1456
|
attributionStyle: 0.85, // Very high - blames self for all errors
|
|
1205
1457
|
metacognitivePlanning: 0.25, // Low - doesn't know what to plan for
|
|
1206
|
-
|
|
1458
|
+
// 0.5, corrected 2026-08-03 from 0.4, and it is a REASONED MIDPOINT rather
|
|
1459
|
+
// than an unfilled default -- the two forces genuinely cancel.
|
|
1460
|
+
//
|
|
1461
|
+
// The old value came from the doc's rationale, "slower development of
|
|
1462
|
+
// procedural skills with new interfaces". That describes ACQUISITION
|
|
1463
|
+
// RATE. This trait measures EXECUTION: its own scale runs from "struggles
|
|
1464
|
+
// with sequences, skips steps, confuses order" to "follows procedures
|
|
1465
|
+
// precisely and efficiently". Third instance of the same defect class on
|
|
1466
|
+
// these pages, after timeHorizon and attributionStyle -- a number set for
|
|
1467
|
+
// the construct the rationale describes rather than the one the trait
|
|
1468
|
+
// measures.
|
|
1469
|
+
//
|
|
1470
|
+
// It scored 0.4, IDENTICAL to cognitive-adhd, while carrying higher
|
|
1471
|
+
// working memory (0.40 vs 0.30) and four times the patience (0.80 vs
|
|
1472
|
+
// 0.20). The low end of this scale is impulsive error, and this persona's
|
|
1473
|
+
// own page says older users "make fewer impulsive errors".
|
|
1474
|
+
//
|
|
1475
|
+
// Precision is preserved or improved with age and efficiency is reduced
|
|
1476
|
+
// -- the speed-accuracy tradeoff shifts toward accuracy (Fisk et al.
|
|
1477
|
+
// 2009, Designing for Older Adults). Those net to the middle: the trait
|
|
1478
|
+
// reference's own `medium` band reads "follows most procedures with
|
|
1479
|
+
// occasional errors", which is the honest description.
|
|
1480
|
+
//
|
|
1481
|
+
// Stays BELOW motor-impairment-tremor (0.6), which is cognitively intact
|
|
1482
|
+
// with working memory 0.70 and metacognitive planning 0.70 against this
|
|
1483
|
+
// persona's 0.40 and 0.25. Stays ABOVE first-timer (0.2), which has no
|
|
1484
|
+
// procedural schema at all.
|
|
1485
|
+
proceduralFluency: 0.5,
|
|
1207
1486
|
transferLearning: 0.2, // Low - each new site is confusing
|
|
1208
|
-
authoritySensitivity: 0.
|
|
1487
|
+
authoritySensitivity: 0.7, // Very high - trusts official-looking things
|
|
1209
1488
|
emotionalContagion: 0.6, // Medium-high - affected by stern warnings
|
|
1210
1489
|
fearOfMissingOut: 0.3, // Low - not driven by urgency, confused by it
|
|
1211
1490
|
socialProofSensitivity: 0.7, // High - relies on grandchildren's recommendations
|
|
1212
|
-
|
|
1213
|
-
siteFamiliarity: 0.5, // Medium - knows the basics
|
|
1491
|
+
mentalModelFlexibility: 0.2, // Very low - rigid, struggles with novel UIs
|
|
1214
1492
|
},
|
|
1215
1493
|
context: {
|
|
1216
1494
|
viewport: [1280, 800],
|
|
@@ -1265,37 +1543,154 @@ export const BUILTIN_PERSONAS = {
|
|
|
1265
1543
|
},
|
|
1266
1544
|
cognitiveTraits: {
|
|
1267
1545
|
patience: 0.1, // Very low - abandons instantly
|
|
1268
|
-
riskTolerance: 0.
|
|
1269
|
-
comprehension: 0.
|
|
1270
|
-
persistence: 0.
|
|
1271
|
-
curiosity: 0.
|
|
1546
|
+
riskTolerance: 0.6, // High - clicks first thing
|
|
1547
|
+
comprehension: 0.6, // Medium
|
|
1548
|
+
persistence: 0.2, // Very low - one strike and out
|
|
1549
|
+
curiosity: 0.3, // Very low - no time to explore
|
|
1272
1550
|
workingMemory: 0.6, // Medium
|
|
1273
|
-
readingTendency: 0.
|
|
1274
|
-
resilience: 0.
|
|
1275
|
-
selfEfficacy: 0.
|
|
1551
|
+
readingTendency: 0.1, // Almost none - scanning only
|
|
1552
|
+
resilience: 0.3, // Very low - no recovery, abandons (BRS)
|
|
1553
|
+
selfEfficacy: 0.6, // Medium - impatient doesn't mean incapable (Bandura)
|
|
1276
1554
|
satisficing: 0.9, // Very high - definition of satisficing (Simon)
|
|
1277
1555
|
trustCalibration: 0.7, // High - clicks through without reading (Fogg)
|
|
1278
1556
|
interruptRecovery: 0.2, // Very low - abandons rather than resumes (Mark)
|
|
1279
1557
|
// New traits (v15.0.0)
|
|
1280
1558
|
informationForaging: 0.9, // Very high - follows first scent, moves on
|
|
1281
|
-
changeBlindness: 0.
|
|
1559
|
+
changeBlindness: 0.7, // Medium - focused on task
|
|
1282
1560
|
anchoringBias: 0.6, // Medium-high - goes with first option
|
|
1283
1561
|
timeHorizon: 0.95, // Maximum short-term - no time for later
|
|
1284
1562
|
attributionStyle: 0.3, // Low - blames slow site
|
|
1285
|
-
metacognitivePlanning: 0.
|
|
1286
|
-
proceduralFluency: 0.
|
|
1563
|
+
metacognitivePlanning: 0.3, // Very low - no planning, just clicking
|
|
1564
|
+
proceduralFluency: 0.6, // Medium - can follow if fast
|
|
1287
1565
|
transferLearning: 0.7, // High - recognizes patterns quickly
|
|
1288
1566
|
authoritySensitivity: 0.4, // Medium - only if it speeds things up
|
|
1289
1567
|
emotionalContagion: 0.4, // Medium - focused on goal, not tone
|
|
1290
|
-
fearOfMissingOut: 0.
|
|
1291
|
-
socialProofSensitivity: 0.
|
|
1292
|
-
|
|
1293
|
-
siteFamiliarity: 0.2, // Low - site structure feels different each visit
|
|
1568
|
+
fearOfMissingOut: 0.8, // Very high - urgency works on them
|
|
1569
|
+
socialProofSensitivity: 0.4, // Medium - if it's quick to evaluate
|
|
1570
|
+
mentalModelFlexibility: 0.6, // High - adapts quickly, expects conventions
|
|
1294
1571
|
},
|
|
1295
1572
|
context: {
|
|
1296
1573
|
viewport: [1280, 800],
|
|
1297
1574
|
},
|
|
1298
1575
|
},
|
|
1576
|
+
// Four personas that had a values profile in the Schwartz registry and no
|
|
1577
|
+
// definition here, so nothing could be RUN as them: empathy_audit,
|
|
1578
|
+
// cognitive_journey and every other persona-driven tool rejected the name
|
|
1579
|
+
// while persona_values_lookup happily returned a full motivational profile.
|
|
1580
|
+
// The values were authored and coherent -- explorer at selfDirection 0.9 /
|
|
1581
|
+
// stimulation 0.9 / security 0.2 is a deliberate description, not a stub --
|
|
1582
|
+
// so the missing half is written here rather than the authored half deleted.
|
|
1583
|
+
// Traits are chosen to be consistent with each one's existing values.
|
|
1584
|
+
// (2026-07-31)
|
|
1585
|
+
"distracted-user": {
|
|
1586
|
+
name: "distracted-user",
|
|
1587
|
+
description: "Attention repeatedly pulled away mid-task; returns with context lost",
|
|
1588
|
+
demographics: { age_range: "18-55", tech_level: "intermediate", device: "desktop" },
|
|
1589
|
+
behaviors: { loses_place: true, task_switches: true, rereads: true },
|
|
1590
|
+
humanBehavior: {
|
|
1591
|
+
timing: {
|
|
1592
|
+
reactionTime: { min: 250, max: 1400 }, clickDelay: { min: 120, max: 500 },
|
|
1593
|
+
typeSpeed: { min: 25, max: 70 }, readingSpeed: 200,
|
|
1594
|
+
scrollPauseTime: { min: 200, max: 1500 },
|
|
1595
|
+
},
|
|
1596
|
+
errors: { misClickRate: 0.09, doubleClickAccidental: 0.04, typoRate: 0.08, backtrackRate: 0.35 },
|
|
1597
|
+
mouse: { curvature: 0.4, jitter: 8, overshoot: 0.15, speed: "normal" },
|
|
1598
|
+
attention: { pattern: "skim", scrollBehavior: "jump", focusAreas: ["header", "cta"], distractionRate: 0.85 },
|
|
1599
|
+
},
|
|
1600
|
+
cognitiveTraits: {
|
|
1601
|
+
patience: 0.4, riskTolerance: 0.5, comprehension: 0.5, persistence: 0.3,
|
|
1602
|
+
curiosity: 0.6, workingMemory: 0.25, readingTendency: 0.3, resilience: 0.4,
|
|
1603
|
+
selfEfficacy: 0.45, satisficing: 0.7, trustCalibration: 0.5,
|
|
1604
|
+
interruptRecovery: 0.1, // The defining trait: context is not recovered
|
|
1605
|
+
informationForaging: 0.6, changeBlindness: 0.8, anchoringBias: 0.6,
|
|
1606
|
+
timeHorizon: 0.7, attributionStyle: 0.4, metacognitivePlanning: 0.2,
|
|
1607
|
+
proceduralFluency: 0.5, transferLearning: 0.5, authoritySensitivity: 0.5,
|
|
1608
|
+
emotionalContagion: 0.5, fearOfMissingOut: 0.7, socialProofSensitivity: 0.5,
|
|
1609
|
+
mentalModelFlexibility: 0.5,
|
|
1610
|
+
},
|
|
1611
|
+
context: { viewport: [1280, 800] },
|
|
1612
|
+
},
|
|
1613
|
+
"careful-reader": {
|
|
1614
|
+
name: "careful-reader",
|
|
1615
|
+
description: "Reads before acting; verifies details and dislikes surprises",
|
|
1616
|
+
demographics: { age_range: "25-65", tech_level: "intermediate", device: "desktop" },
|
|
1617
|
+
behaviors: { reads_fully: true, verifies_before_submit: true, avoids_risk: true },
|
|
1618
|
+
humanBehavior: {
|
|
1619
|
+
timing: {
|
|
1620
|
+
reactionTime: { min: 600, max: 2500 }, clickDelay: { min: 300, max: 900 },
|
|
1621
|
+
typeSpeed: { min: 30, max: 80 }, readingSpeed: 130,
|
|
1622
|
+
scrollPauseTime: { min: 800, max: 3000 },
|
|
1623
|
+
},
|
|
1624
|
+
errors: { misClickRate: 0.02, doubleClickAccidental: 0.01, typoRate: 0.02, backtrackRate: 0.08 },
|
|
1625
|
+
mouse: { curvature: 0.2, jitter: 3, overshoot: 0.03, speed: "slow" },
|
|
1626
|
+
attention: { pattern: "thorough", scrollBehavior: "continuous", focusAreas: ["text", "prices"], distractionRate: 0.1 },
|
|
1627
|
+
},
|
|
1628
|
+
cognitiveTraits: {
|
|
1629
|
+
patience: 0.9, riskTolerance: 0.15, comprehension: 0.8, persistence: 0.8,
|
|
1630
|
+
curiosity: 0.5, workingMemory: 0.7, readingTendency: 0.95, resilience: 0.7,
|
|
1631
|
+
selfEfficacy: 0.6, satisficing: 0.1, trustCalibration: 0.25,
|
|
1632
|
+
interruptRecovery: 0.7, informationForaging: 0.4, changeBlindness: 0.2,
|
|
1633
|
+
anchoringBias: 0.3, timeHorizon: 0.3, attributionStyle: 0.6,
|
|
1634
|
+
metacognitivePlanning: 0.8, proceduralFluency: 0.6, transferLearning: 0.6,
|
|
1635
|
+
authoritySensitivity: 0.6, emotionalContagion: 0.3, fearOfMissingOut: 0.15,
|
|
1636
|
+
socialProofSensitivity: 0.4, mentalModelFlexibility: 0.4,
|
|
1637
|
+
},
|
|
1638
|
+
context: { viewport: [1280, 800] },
|
|
1639
|
+
},
|
|
1640
|
+
"explorer": {
|
|
1641
|
+
name: "explorer",
|
|
1642
|
+
description: "Wanders the interface by choice, opening things to see what they do",
|
|
1643
|
+
demographics: { age_range: "18-45", tech_level: "expert", device: "desktop" },
|
|
1644
|
+
behaviors: { wanders: true, tries_everything: true, ignores_happy_path: true },
|
|
1645
|
+
humanBehavior: {
|
|
1646
|
+
timing: {
|
|
1647
|
+
reactionTime: { min: 200, max: 900 }, clickDelay: { min: 100, max: 350 },
|
|
1648
|
+
typeSpeed: { min: 45, max: 110 }, readingSpeed: 250,
|
|
1649
|
+
scrollPauseTime: { min: 200, max: 1200 },
|
|
1650
|
+
},
|
|
1651
|
+
errors: { misClickRate: 0.05, doubleClickAccidental: 0.02, typoRate: 0.04, backtrackRate: 0.25 },
|
|
1652
|
+
mouse: { curvature: 0.5, jitter: 6, overshoot: 0.12, speed: "fast" },
|
|
1653
|
+
attention: { pattern: "z-pattern", scrollBehavior: "chunked", focusAreas: ["header", "images", "cta"], distractionRate: 0.5 },
|
|
1654
|
+
},
|
|
1655
|
+
cognitiveTraits: {
|
|
1656
|
+
patience: 0.7, riskTolerance: 0.9, comprehension: 0.75, persistence: 0.7,
|
|
1657
|
+
curiosity: 0.95, workingMemory: 0.65, readingTendency: 0.4, resilience: 0.8,
|
|
1658
|
+
selfEfficacy: 0.85, satisficing: 0.2, trustCalibration: 0.6,
|
|
1659
|
+
interruptRecovery: 0.7, informationForaging: 0.9, changeBlindness: 0.3,
|
|
1660
|
+
anchoringBias: 0.25, timeHorizon: 0.35, attributionStyle: 0.7,
|
|
1661
|
+
metacognitivePlanning: 0.5, proceduralFluency: 0.7, transferLearning: 0.85,
|
|
1662
|
+
authoritySensitivity: 0.2, emotionalContagion: 0.4, fearOfMissingOut: 0.4,
|
|
1663
|
+
socialProofSensitivity: 0.25, mentalModelFlexibility: 0.75,
|
|
1664
|
+
},
|
|
1665
|
+
context: { viewport: [1440, 900] },
|
|
1666
|
+
},
|
|
1667
|
+
"task-focused": {
|
|
1668
|
+
name: "task-focused",
|
|
1669
|
+
description: "Came to finish one thing; ignores everything that is not on the path",
|
|
1670
|
+
demographics: { age_range: "25-55", tech_level: "intermediate", device: "desktop" },
|
|
1671
|
+
behaviors: { goal_directed: true, ignores_promotions: true, resents_detours: true },
|
|
1672
|
+
humanBehavior: {
|
|
1673
|
+
timing: {
|
|
1674
|
+
reactionTime: { min: 200, max: 800 }, clickDelay: { min: 100, max: 300 },
|
|
1675
|
+
typeSpeed: { min: 40, max: 100 }, readingSpeed: 260,
|
|
1676
|
+
scrollPauseTime: { min: 150, max: 600 },
|
|
1677
|
+
},
|
|
1678
|
+
errors: { misClickRate: 0.04, doubleClickAccidental: 0.02, typoRate: 0.04, backtrackRate: 0.12 },
|
|
1679
|
+
mouse: { curvature: 0.2, jitter: 4, overshoot: 0.06, speed: "fast" },
|
|
1680
|
+
attention: { pattern: "f-pattern", scrollBehavior: "jump", focusAreas: ["cta", "text"], distractionRate: 0.15 },
|
|
1681
|
+
},
|
|
1682
|
+
cognitiveTraits: {
|
|
1683
|
+
patience: 0.6, riskTolerance: 0.5, comprehension: 0.7, persistence: 0.9,
|
|
1684
|
+
curiosity: 0.2, workingMemory: 0.7, readingTendency: 0.35, resilience: 0.75,
|
|
1685
|
+
selfEfficacy: 0.8, satisficing: 0.5, trustCalibration: 0.5,
|
|
1686
|
+
interruptRecovery: 0.8, informationForaging: 0.7, changeBlindness: 0.6,
|
|
1687
|
+
anchoringBias: 0.45, timeHorizon: 0.6, attributionStyle: 0.6,
|
|
1688
|
+
metacognitivePlanning: 0.75, proceduralFluency: 0.8, transferLearning: 0.7,
|
|
1689
|
+
authoritySensitivity: 0.4, emotionalContagion: 0.25, fearOfMissingOut: 0.3,
|
|
1690
|
+
socialProofSensitivity: 0.2, mentalModelFlexibility: 0.6,
|
|
1691
|
+
},
|
|
1692
|
+
context: { viewport: [1280, 800] },
|
|
1693
|
+
},
|
|
1299
1694
|
};
|
|
1300
1695
|
/**
|
|
1301
1696
|
* Get a persona by name.
|
|
@@ -1329,7 +1724,7 @@ export function listCustomPersonas() {
|
|
|
1329
1724
|
* Get the custom personas directory path.
|
|
1330
1725
|
*/
|
|
1331
1726
|
export function getPersonasDir() {
|
|
1332
|
-
return
|
|
1727
|
+
return personasDirFor();
|
|
1333
1728
|
}
|
|
1334
1729
|
/**
|
|
1335
1730
|
* Built-in accessibility personas for empathy testing.
|
|
@@ -1394,37 +1789,49 @@ export const ACCESSIBILITY_PERSONAS = {
|
|
|
1394
1789
|
cognitiveTraits: {
|
|
1395
1790
|
// Research: Motor impairment + self-efficacy (Lorig et al., 2001 - Chronic Disease Self-Management)
|
|
1396
1791
|
// Adapted users maintain moderate efficacy despite physical challenges
|
|
1397
|
-
selfEfficacy: 0.
|
|
1792
|
+
selfEfficacy: 0.6,
|
|
1398
1793
|
// Research: Physical effort increases satisficing (Kool et al., 2010 - Effort discounting)
|
|
1399
1794
|
// Motor strain leads to accepting "good enough" to minimize fatigue
|
|
1400
|
-
|
|
1401
|
-
//
|
|
1402
|
-
|
|
1795
|
+
// High = first adequate option. Each additional comparison means another
|
|
1796
|
+
// set of pointing operations.
|
|
1797
|
+
satisficing: 0.75,
|
|
1798
|
+
trustCalibration: 0.6,
|
|
1403
1799
|
// Research: Motor issues make resumption harder but adaptation helps (Mark)
|
|
1404
|
-
|
|
1405
|
-
//
|
|
1406
|
-
|
|
1407
|
-
|
|
1800
|
+
// Re-acquiring a small target after an interruption repeats the hardest
|
|
1801
|
+
// part of the interaction.
|
|
1802
|
+
interruptRecovery: 0.6,
|
|
1803
|
+
// Every pointing action costs time and repeat attempts, so tolerance for
|
|
1804
|
+
// slow interaction is built in -- the persona's own research note records
|
|
1805
|
+
// 1-15Hz tremor and misclicks as the primary barrier.
|
|
1806
|
+
patience: 0.8,
|
|
1807
|
+
// Low = only clicks obvious, labelled controls. An accidental click is
|
|
1808
|
+
// expensive to undo when re-pointing is itself hard.
|
|
1809
|
+
riskTolerance: 0.3,
|
|
1408
1810
|
comprehension: 0.7,
|
|
1811
|
+
// A missed target is retried rather than abandoned; the alternative is not
|
|
1812
|
+
// completing the task at all.
|
|
1409
1813
|
persistence: 0.7,
|
|
1410
1814
|
curiosity: 0.4,
|
|
1411
1815
|
workingMemory: 0.7,
|
|
1412
1816
|
readingTendency: 0.6,
|
|
1413
1817
|
resilience: 0.6,
|
|
1414
|
-
|
|
1818
|
+
// Low = exhaustive rather than scent-following. Exploratory clicking is
|
|
1819
|
+
// expensive, so paths are chosen carefully and few are sampled.
|
|
1820
|
+
informationForaging: 0.35,
|
|
1415
1821
|
changeBlindness: 0.4,
|
|
1416
1822
|
anchoringBias: 0.5,
|
|
1417
1823
|
timeHorizon: 0.4, // Patient due to motor constraints
|
|
1418
1824
|
attributionStyle: 0.4, // Blames physical constraints, not self
|
|
1419
|
-
|
|
1825
|
+
// Target order and approach are planned to minimise pointing: keyboard
|
|
1826
|
+
// where possible, large targets first.
|
|
1827
|
+
metacognitivePlanning: 0.7,
|
|
1420
1828
|
proceduralFluency: 0.6,
|
|
1421
1829
|
transferLearning: 0.6,
|
|
1422
1830
|
authoritySensitivity: 0.5,
|
|
1423
1831
|
emotionalContagion: 0.4,
|
|
1424
1832
|
fearOfMissingOut: 0.3, // Not swayed, focused on completing
|
|
1425
1833
|
socialProofSensitivity: 0.5,
|
|
1426
|
-
|
|
1427
|
-
siteFamiliarity: 0.5, // Medium - regular user with motor challenges
|
|
1834
|
+
mentalModelFlexibility: 0.5,
|
|
1428
1835
|
},
|
|
1429
1836
|
},
|
|
1430
1837
|
"low-vision-magnified": {
|
|
@@ -1475,6 +1882,17 @@ export const ACCESSIBILITY_PERSONAS = {
|
|
|
1475
1882
|
viewport: [1280, 800], // But effectively sees 1/9th at a time
|
|
1476
1883
|
},
|
|
1477
1884
|
accessibilityTraits: {
|
|
1885
|
+
// Reading capacity, stated rather than inferred from the persona's NAME.
|
|
1886
|
+
// These are the same values getReadingProfile returned for this persona
|
|
1887
|
+
// via name matching, so behaviour is unchanged -- but they are now
|
|
1888
|
+
// editable, which they were not: no trait change could move WPM, fixation
|
|
1889
|
+
// span or phonological penalty. Source: Legge et al. (2007) -- central
|
|
1890
|
+
// scotoma and crowding. (2026-08-02)
|
|
1891
|
+
orthographicFluency: 0.6,
|
|
1892
|
+
phonologicalDecoding: 0.75,
|
|
1893
|
+
visualSpan: 3,
|
|
1894
|
+
vocabularyBreadth: 0.75,
|
|
1895
|
+
crowdingSensitivity: 0.7,
|
|
1478
1896
|
visionLevel: 0.3,
|
|
1479
1897
|
contrastSensitivity: 3.0,
|
|
1480
1898
|
processingSpeed: 0.7,
|
|
@@ -1484,10 +1902,10 @@ export const ACCESSIBILITY_PERSONAS = {
|
|
|
1484
1902
|
cognitiveTraits: {
|
|
1485
1903
|
// Research: Visual impairment + self-efficacy (Brody et al., 2002 - AMD and depression)
|
|
1486
1904
|
// Reduced vision correlates with lower confidence in task completion
|
|
1487
|
-
selfEfficacy: 0.
|
|
1905
|
+
selfEfficacy: 0.6,
|
|
1488
1906
|
// Research: Limited information access increases satisficing (Pachur & Hertwig, 2006)
|
|
1489
1907
|
// Seeing only 1/9th of screen at a time → accept accessible options
|
|
1490
|
-
satisficing: 0.
|
|
1908
|
+
satisficing: 0.4,
|
|
1491
1909
|
// Research: Vision impairment increases caution (Brody 2002)
|
|
1492
1910
|
trustCalibration: 0.4,
|
|
1493
1911
|
// Research: Limited visible area makes context recovery harder (Mark)
|
|
@@ -1495,26 +1913,25 @@ export const ACCESSIBILITY_PERSONAS = {
|
|
|
1495
1913
|
// New traits (v15.0.0)
|
|
1496
1914
|
patience: 0.7,
|
|
1497
1915
|
riskTolerance: 0.3,
|
|
1498
|
-
comprehension: 0.
|
|
1499
|
-
persistence: 0.
|
|
1916
|
+
comprehension: 0.7,
|
|
1917
|
+
persistence: 0.8,
|
|
1500
1918
|
curiosity: 0.3,
|
|
1501
1919
|
workingMemory: 0.6,
|
|
1502
|
-
readingTendency: 0.
|
|
1503
|
-
resilience: 0.
|
|
1920
|
+
readingTendency: 0.9, // Reads carefully when visible
|
|
1921
|
+
resilience: 0.7,
|
|
1504
1922
|
informationForaging: 0.4, // Limited by zoom - systematic search
|
|
1505
1923
|
changeBlindness: 0.8, // Very high - can't see peripheral
|
|
1506
1924
|
anchoringBias: 0.6, // Anchored due to limited comparison
|
|
1507
1925
|
timeHorizon: 0.4, // Patient, knows it takes time
|
|
1508
1926
|
attributionStyle: 0.5, // Balanced - knows about limitations
|
|
1509
1927
|
metacognitivePlanning: 0.7, // Plans navigation with zoom
|
|
1510
|
-
proceduralFluency: 0.
|
|
1511
|
-
transferLearning: 0.
|
|
1928
|
+
proceduralFluency: 0.6, // Harder with limited view
|
|
1929
|
+
transferLearning: 0.6, // Standard
|
|
1512
1930
|
authoritySensitivity: 0.5,
|
|
1513
1931
|
emotionalContagion: 0.4,
|
|
1514
|
-
fearOfMissingOut: 0.
|
|
1932
|
+
fearOfMissingOut: 0.4, // Not swayed - focused
|
|
1515
1933
|
socialProofSensitivity: 0.5,
|
|
1516
|
-
|
|
1517
|
-
siteFamiliarity: 0.3, // Low - magnification makes layout unfamiliar
|
|
1934
|
+
mentalModelFlexibility: 0.4, // Adapts but needs time
|
|
1518
1935
|
},
|
|
1519
1936
|
},
|
|
1520
1937
|
"cognitive-adhd": {
|
|
@@ -1564,38 +1981,83 @@ export const ACCESSIBILITY_PERSONAS = {
|
|
|
1564
1981
|
viewport: [1920, 1080],
|
|
1565
1982
|
},
|
|
1566
1983
|
accessibilityTraits: {
|
|
1984
|
+
// Reading capacity, stated rather than inferred from the persona's NAME.
|
|
1985
|
+
// These are the same values getReadingProfile returned for this persona
|
|
1986
|
+
// via name matching, so behaviour is unchanged -- but they are now
|
|
1987
|
+
// editable, which they were not: no trait change could move WPM, fixation
|
|
1988
|
+
// span or phonological penalty. Source: Dhar et al. (2010) -- intact
|
|
1989
|
+
// decoding, reduced sustained attention. (2026-08-02)
|
|
1990
|
+
orthographicFluency: 0.8,
|
|
1991
|
+
phonologicalDecoding: 0.75,
|
|
1992
|
+
visualSpan: 6,
|
|
1993
|
+
vocabularyBreadth: 0.7,
|
|
1994
|
+
crowdingSensitivity: 0.2,
|
|
1567
1995
|
processingSpeed: 0.6, // Variable - can be fast when interested
|
|
1568
1996
|
attentionSpan: 0.3, // Short sustained attention
|
|
1569
1997
|
fatigueSusceptibility: 0.4,
|
|
1570
1998
|
},
|
|
1999
|
+
// Reconciled against Persona-ADHD.md, the persona's own published trait
|
|
2000
|
+
// table, on 2026-08-02. Nineteen of twenty-five values disagreed. Each was
|
|
2001
|
+
// arbitrated against trait-reference.ts -- which names specific personas as
|
|
2002
|
+
// typically high or low per trait and defines what each end of the scale
|
|
2003
|
+
// MEANS -- rather than by preferring one file over the other.
|
|
2004
|
+
//
|
|
2005
|
+
// Fifteen adopted the doc's value; the doc was corrected on the other four,
|
|
2006
|
+
// which are recorded in Persona-ADHD.md. The four are worth naming because
|
|
2007
|
+
// they are all one failure: a number written against the plain-English
|
|
2008
|
+
// reading of a trait's NAME instead of its documented scale.
|
|
2009
|
+
//
|
|
2010
|
+
// timeHorizon doc said 0.3, meaning "long-term focused"
|
|
2011
|
+
// attributionStyle doc said 0.3, meaning "blames the system"
|
|
2012
|
+
// mentalModelFlexibility doc said 0.4, meaning "somewhat rigid"
|
|
2013
|
+
// trustCalibration doc said 0.5, meaning "neutral"
|
|
2014
|
+
//
|
|
2015
|
+
// In each case the doc's own RATIONALE argued for the opposite number. It
|
|
2016
|
+
// said "strong preference for immediate rewards" beside 0.3 on a scale
|
|
2017
|
+
// whose 1.0 end is literally "Immediate gratification, wants results NOW",
|
|
2018
|
+
// and "may blame self" beside 0.3 on a scale whose 1.0 end is "Blames
|
|
2019
|
+
// self". The prose was right every time; the digit was inverted.
|
|
1571
2020
|
cognitiveTraits: {
|
|
1572
|
-
workingMemory: 0.
|
|
1573
|
-
patience: 0.
|
|
1574
|
-
persistence: 0.
|
|
1575
|
-
curiosity: 0.
|
|
2021
|
+
workingMemory: 0.3, // Research: large magnitude impairment (d=1.63-2.03)
|
|
2022
|
+
patience: 0.2, // Impulsivity: low tolerance for waiting
|
|
2023
|
+
persistence: 0.3, // Low for unengaging tasks; can hyperfocus on interesting ones
|
|
2024
|
+
curiosity: 0.9, // High novelty-seeking
|
|
1576
2025
|
riskTolerance: 0.7, // Impulsive clicking
|
|
1577
2026
|
readingTendency: 0.2, // Skims rather than reads
|
|
1578
|
-
resilience: 0.
|
|
2027
|
+
resilience: 0.4, // Emotional dysregulation is common (doc; code had 0.55)
|
|
1579
2028
|
selfEfficacy: 0.4, // Variable - can feel capable when engaged (Bandura)
|
|
1580
|
-
satisficing: 0.
|
|
1581
|
-
|
|
1582
|
-
|
|
2029
|
+
satisficing: 0.7, // High - ADHD drives "good enough" decisions (Simon)
|
|
2030
|
+
// KEPT over the doc's 0.5: trait-reference lists cognitive-adhd under
|
|
2031
|
+
// typicalScores.high, and 1.0 on this scale is "highly trusting, accepts
|
|
2032
|
+
// claims at face value" -- which is what impulsive clicking without
|
|
2033
|
+
// reading looks like.
|
|
2034
|
+
trustCalibration: 0.65,
|
|
2035
|
+
interruptRecovery: 0.3, // Very low - WM deficits make recovery difficult (Mark)
|
|
1583
2036
|
// New traits (v15.0.0)
|
|
1584
|
-
comprehension: 0.
|
|
1585
|
-
informationForaging: 0.
|
|
1586
|
-
changeBlindness: 0.
|
|
1587
|
-
anchoringBias: 0.
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
2037
|
+
comprehension: 0.6, // Capable when engaged; this is UI-convention grasp, not reading
|
|
2038
|
+
informationForaging: 0.4, // Distractible; goes down tangential paths (doc; code had 0.6)
|
|
2039
|
+
changeBlindness: 0.6, // High - focus elsewhere when changes happen
|
|
2040
|
+
anchoringBias: 0.6, // First option favored, decision-fatigue avoidance (doc; code had 0.4)
|
|
2041
|
+
// KEPT over the doc's 0.3. 1.0 on this scale is "Immediate gratification,
|
|
2042
|
+
// wants results NOW" -- the name reads like "how far ahead do you look",
|
|
2043
|
+
// and it means the opposite. trait-reference lists cognitive-adhd under
|
|
2044
|
+
// typicalScores.high alongside impatient-user and mobile-user.
|
|
2045
|
+
timeHorizon: 0.9,
|
|
2046
|
+
// KEPT over the doc's 0.3. 1.0 is "Blames self (internal attribution)",
|
|
2047
|
+
// and the doc's own rationale for 0.3 was "may blame self".
|
|
2048
|
+
attributionStyle: 0.6,
|
|
2049
|
+
metacognitivePlanning: 0.3, // Very low - impulsive, no planning
|
|
2050
|
+
proceduralFluency: 0.4, // Inconsistent; routines help but are hard to establish
|
|
2051
|
+
transferLearning: 0.5, // Variable; depends on engagement level
|
|
1593
2052
|
authoritySensitivity: 0.4, // Low - impulsive, ignores authority
|
|
1594
2053
|
emotionalContagion: 0.6, // Medium-high - emotional variability
|
|
1595
|
-
fearOfMissingOut: 0.
|
|
2054
|
+
fearOfMissingOut: 0.7, // High - ADHD correlates with FOMO
|
|
1596
2055
|
socialProofSensitivity: 0.5, // Medium - if interesting
|
|
1597
|
-
|
|
1598
|
-
|
|
2056
|
+
// KEPT over the doc's 0.4. 1.0 is "Highly adaptive - quickly forms new
|
|
2057
|
+
// mental models"; the doc's rationale was "flexible thinking, sometimes
|
|
2058
|
+
// too flexible". A fourth instance of the rigidity/flexibility inversion
|
|
2059
|
+
// that commit 086d519 fixed in three other pages.
|
|
2060
|
+
mentalModelFlexibility: 0.7,
|
|
1599
2061
|
},
|
|
1600
2062
|
},
|
|
1601
2063
|
"dyslexic-user": {
|
|
@@ -1645,38 +2107,81 @@ export const ACCESSIBILITY_PERSONAS = {
|
|
|
1645
2107
|
viewport: [1280, 800],
|
|
1646
2108
|
},
|
|
1647
2109
|
accessibilityTraits: {
|
|
2110
|
+
// Reading capacity, stated rather than inferred from the persona's NAME.
|
|
2111
|
+
// These are the same values getReadingProfile returned for this persona
|
|
2112
|
+
// via name matching, so behaviour is unchanged -- but they are now
|
|
2113
|
+
// editable, which they were not: no trait change could move WPM, fixation
|
|
2114
|
+
// span or phonological penalty. Source: Perry, Zorzi & Ziegler (2019),
|
|
2115
|
+
// Psychological Science. (2026-08-02)
|
|
2116
|
+
orthographicFluency: 0.4,
|
|
2117
|
+
phonologicalDecoding: 0.35,
|
|
2118
|
+
visualSpan: 4,
|
|
2119
|
+
vocabularyBreadth: 0.65,
|
|
2120
|
+
crowdingSensitivity: 0.55,
|
|
1648
2121
|
processingSpeed: 0.5, // Slower text processing
|
|
1649
2122
|
attentionSpan: 0.5,
|
|
1650
2123
|
fatigueSusceptibility: 0.6, // Reading requires more effort
|
|
1651
2124
|
},
|
|
1652
2125
|
cognitiveTraits: {
|
|
1653
|
-
|
|
1654
|
-
|
|
2126
|
+
// WM deficit persists into adulthood across phonological AND visuospatial
|
|
2127
|
+
// modalities; a cognitive marker distinguishing dyslexic from typical
|
|
2128
|
+
// readers in every European orthography (de Jong 2006; n-back fNIRS,
|
|
2129
|
+
// PMC3496727). Was 0.6 -- above average -- which inverted one of the best-
|
|
2130
|
+
// established findings in the literature.
|
|
2131
|
+
workingMemory: 0.3,
|
|
2132
|
+
// Slower reading is one of three documented compensatory mechanisms,
|
|
2133
|
+
// alongside text-structure use and verbal ability (Annals of Dyslexia,
|
|
2134
|
+
// 10.1007/s11881-020-00195-w). Taking extra time with text is the
|
|
2135
|
+
// strategy, not a failure of tolerance.
|
|
2136
|
+
patience: 0.75,
|
|
1655
2137
|
curiosity: 0.7,
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
2138
|
+
// Relies on structure and skimming over sustained prose. Note this is a
|
|
2139
|
+
// STRATEGY, not decoding ability -- decoding now enters the chain via
|
|
2140
|
+
// readingCapacity, bridged from getReadingProfile.
|
|
2141
|
+
readingTendency: 0.35,
|
|
2142
|
+
// Pulled down from 0.6 for documented secondary anxiety (Kapur & Agrawal
|
|
2143
|
+
// 2026), but not lower: the compensation literature describes adults
|
|
2144
|
+
// achieving academic success, so learned helplessness would overstate it.
|
|
2145
|
+
resilience: 0.6,
|
|
2146
|
+
// Dyslexia is a strong predictor of lower academic self-efficacy in higher
|
|
2147
|
+
// education (PMC11488781; Nigerian undergraduate cohort).
|
|
2148
|
+
selfEfficacy: 0.3,
|
|
2149
|
+
// Reading is the expensive operation, so the first adequate option is
|
|
2150
|
+
// strongly preferred over an exhaustive comparison.
|
|
2151
|
+
satisficing: 0.7,
|
|
1660
2152
|
trustCalibration: 0.5, // Medium - standard trust evaluation (Fogg)
|
|
1661
|
-
|
|
2153
|
+
// Follows from the WM deficit: resuming a task means reloading context
|
|
2154
|
+
// that is expensive to hold.
|
|
2155
|
+
interruptRecovery: 0.35,
|
|
1662
2156
|
// New traits (v15.0.0)
|
|
1663
|
-
riskTolerance: 0.
|
|
2157
|
+
riskTolerance: 0.4,
|
|
1664
2158
|
comprehension: 0.5, // Comprehension fine for visuals
|
|
1665
|
-
|
|
1666
|
-
|
|
2159
|
+
// The same compensation literature: strategies are built and sustained
|
|
2160
|
+
// across years of schooling, and mastery experience feeds back into
|
|
2161
|
+
// persistence.
|
|
2162
|
+
persistence: 0.75,
|
|
2163
|
+
// Text-structure sensitivity is the second documented compensator:
|
|
2164
|
+
// headings and layout are used as scent rather than reading everything,
|
|
2165
|
+
// which is the high end of this scale.
|
|
2166
|
+
informationForaging: 0.65,
|
|
1667
2167
|
changeBlindness: 0.4, // Lower - visual learner
|
|
1668
|
-
anchoringBias: 0.
|
|
2168
|
+
anchoringBias: 0.6,
|
|
1669
2169
|
timeHorizon: 0.5,
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
2170
|
+
// High = blames self. Psychoeducation framing dyslexia as
|
|
2171
|
+
// neurodevelopmental rather than personal inadequacy measurably REDUCES
|
|
2172
|
+
// self-blame, which places the untreated baseline above neutral (Kapur &
|
|
2173
|
+
// Agrawal 2026).
|
|
2174
|
+
attributionStyle: 0.7,
|
|
2175
|
+
// Deliberate compensatory strategy use IS metacognition -- choosing
|
|
2176
|
+
// structure over linear prose is a planned approach, not a reflex.
|
|
2177
|
+
metacognitivePlanning: 0.7,
|
|
2178
|
+
proceduralFluency: 0.4,
|
|
1673
2179
|
transferLearning: 0.6, // Recognizes visual patterns
|
|
1674
2180
|
authoritySensitivity: 0.5,
|
|
1675
2181
|
emotionalContagion: 0.5,
|
|
1676
|
-
fearOfMissingOut: 0.
|
|
2182
|
+
fearOfMissingOut: 0.4,
|
|
1677
2183
|
socialProofSensitivity: 0.6, // Relies on visual reviews
|
|
1678
|
-
|
|
1679
|
-
siteFamiliarity: 0.5, // Medium - knows sites but reading is hard
|
|
2184
|
+
mentalModelFlexibility: 0.6, // Good adaptation
|
|
1680
2185
|
},
|
|
1681
2186
|
},
|
|
1682
2187
|
"deaf-user": {
|
|
@@ -1729,33 +2234,32 @@ export const ACCESSIBILITY_PERSONAS = {
|
|
|
1729
2234
|
attentionSpan: 0.8,
|
|
1730
2235
|
},
|
|
1731
2236
|
cognitiveTraits: {
|
|
1732
|
-
patience: 0.
|
|
1733
|
-
riskTolerance: 0.
|
|
2237
|
+
patience: 0.6, // Accustomed to finding captions/text alternatives
|
|
2238
|
+
riskTolerance: 0.4, // Standard caution
|
|
1734
2239
|
readingTendency: 0.9, // High - reads all text since can't hear audio
|
|
1735
|
-
resilience: 0.
|
|
1736
|
-
selfEfficacy: 0.
|
|
1737
|
-
satisficing: 0.
|
|
1738
|
-
trustCalibration: 0.
|
|
1739
|
-
interruptRecovery: 0.
|
|
2240
|
+
resilience: 0.7, // High - adapted to audio-free experience (BRS)
|
|
2241
|
+
selfEfficacy: 0.7, // Medium-high - confident in visual navigation (Bandura)
|
|
2242
|
+
satisficing: 0.5, // Medium - seeks captioned/text content (Simon)
|
|
2243
|
+
trustCalibration: 0.6, // Medium - standard visual trust evaluation (Fogg)
|
|
2244
|
+
interruptRecovery: 0.7, // Medium-high - visual cues assist recovery (Mark)
|
|
1740
2245
|
// New traits (v15.0.0)
|
|
1741
|
-
comprehension: 0.
|
|
2246
|
+
comprehension: 0.8,
|
|
1742
2247
|
persistence: 0.7,
|
|
1743
|
-
curiosity: 0.
|
|
1744
|
-
workingMemory: 0.
|
|
2248
|
+
curiosity: 0.6,
|
|
2249
|
+
workingMemory: 0.6,
|
|
1745
2250
|
informationForaging: 0.6, // Good visual navigation
|
|
1746
|
-
changeBlindness: 0.
|
|
2251
|
+
changeBlindness: 0.3, // Very low - visually attentive
|
|
1747
2252
|
anchoringBias: 0.5,
|
|
1748
2253
|
timeHorizon: 0.5,
|
|
1749
2254
|
attributionStyle: 0.4, // Blames lack of captions
|
|
1750
|
-
metacognitivePlanning: 0.
|
|
2255
|
+
metacognitivePlanning: 0.7, // Plans for captioned content
|
|
1751
2256
|
proceduralFluency: 0.7, // Good with visual instructions
|
|
1752
2257
|
transferLearning: 0.7, // Recognizes visual patterns
|
|
1753
2258
|
authoritySensitivity: 0.5,
|
|
1754
|
-
emotionalContagion: 0.
|
|
2259
|
+
emotionalContagion: 0.6, // Less affected by audio tone
|
|
1755
2260
|
fearOfMissingOut: 0.4,
|
|
1756
2261
|
socialProofSensitivity: 0.6, // Visual reviews/ratings
|
|
1757
|
-
|
|
1758
|
-
siteFamiliarity: 0.5, // Medium - visual learner, remembers layout
|
|
2262
|
+
mentalModelFlexibility: 0.65, // Good visual adaptation
|
|
1759
2263
|
},
|
|
1760
2264
|
},
|
|
1761
2265
|
"elderly-low-vision": {
|
|
@@ -1806,6 +2310,21 @@ export const ACCESSIBILITY_PERSONAS = {
|
|
|
1806
2310
|
viewport: [1280, 800],
|
|
1807
2311
|
},
|
|
1808
2312
|
accessibilityTraits: {
|
|
2313
|
+
// This persona is BOTH elderly and low-vision, and the name lookup
|
|
2314
|
+
// resolved it by accident: it tests 'low-vision' before 'elderly', so it
|
|
2315
|
+
// silently returned the low-vision profile and the aging half was never
|
|
2316
|
+
// applied. Rather than preserve an ordering accident, each dimension
|
|
2317
|
+
// takes the MORE impaired of the two profiles -- both conditions impair
|
|
2318
|
+
// reading -- except vocabulary, where age is an advantage: crystallized
|
|
2319
|
+
// vocabulary grows across the lifespan (Rayner et al. 2006), so the
|
|
2320
|
+
// elderly value of 0.85 is kept over low vision's 0.75.
|
|
2321
|
+
// orthographic 0.6 (lowVision) / phonological 0.65 (elderly) /
|
|
2322
|
+
// span 3 (lowVision) / vocabulary 0.85 (elderly) / crowding 0.7 (lowVision).
|
|
2323
|
+
orthographicFluency: 0.6,
|
|
2324
|
+
phonologicalDecoding: 0.65,
|
|
2325
|
+
visualSpan: 3,
|
|
2326
|
+
vocabularyBreadth: 0.85,
|
|
2327
|
+
crowdingSensitivity: 0.7,
|
|
1809
2328
|
motorControl: 0.5,
|
|
1810
2329
|
tremor: false, // Not necessarily present
|
|
1811
2330
|
reachability: 0.6,
|
|
@@ -1816,33 +2335,32 @@ export const ACCESSIBILITY_PERSONAS = {
|
|
|
1816
2335
|
fatigueSusceptibility: 0.7,
|
|
1817
2336
|
},
|
|
1818
2337
|
cognitiveTraits: {
|
|
1819
|
-
workingMemory: 0.
|
|
1820
|
-
patience: 0.
|
|
1821
|
-
persistence: 0.
|
|
2338
|
+
workingMemory: 0.3, // Research: inhibitory control decline limits WM
|
|
2339
|
+
patience: 0.9, // High: more methodical than young users
|
|
2340
|
+
persistence: 0.8, // Determined but confused
|
|
1822
2341
|
curiosity: 0.3, // Low: prefers familiar patterns
|
|
1823
|
-
riskTolerance: 0.
|
|
2342
|
+
riskTolerance: 0.1, // Very cautious with unfamiliar interfaces
|
|
1824
2343
|
comprehension: 0.3, // Unfamiliar with modern UI conventions
|
|
1825
|
-
resilience: 0.
|
|
1826
|
-
selfEfficacy: 0.
|
|
1827
|
-
satisficing: 0.
|
|
1828
|
-
trustCalibration: 0.
|
|
1829
|
-
interruptRecovery: 0.
|
|
2344
|
+
resilience: 0.6, // Low - frustration compounds with physical challenges (BRS)
|
|
2345
|
+
selfEfficacy: 0.3, // Very low - often blame selves for tech issues (Bandura)
|
|
2346
|
+
satisficing: 0.7, // High - avoids complex decision trees (Simon)
|
|
2347
|
+
trustCalibration: 0.4, // Very low - very skeptical of online requests (Fogg)
|
|
2348
|
+
interruptRecovery: 0.3, // Very low - WM + vision decline makes recovery hard (Mark)
|
|
1830
2349
|
// New traits (v15.0.0)
|
|
1831
|
-
readingTendency: 0.
|
|
1832
|
-
informationForaging: 0.
|
|
1833
|
-
changeBlindness: 0.
|
|
2350
|
+
readingTendency: 0.9,
|
|
2351
|
+
informationForaging: 0.4, // Very low - exhaustive, uncertain
|
|
2352
|
+
changeBlindness: 0.7, // High - vision issues
|
|
1834
2353
|
anchoringBias: 0.8, // High - sticks to first info
|
|
1835
2354
|
timeHorizon: 0.4, // Medium - patient but unsure
|
|
1836
2355
|
attributionStyle: 0.9, // Very high - blames self
|
|
1837
2356
|
metacognitivePlanning: 0.2, // Low - doesn't know what to plan
|
|
1838
|
-
proceduralFluency: 0.
|
|
1839
|
-
transferLearning: 0.
|
|
1840
|
-
authoritySensitivity: 0.
|
|
2357
|
+
proceduralFluency: 0.4, // Low - struggles with sequences
|
|
2358
|
+
transferLearning: 0.4, // Very low - each UI is confusing
|
|
2359
|
+
authoritySensitivity: 0.7, // Very high - trusts official things
|
|
1841
2360
|
emotionalContagion: 0.6, // Medium-high
|
|
1842
|
-
fearOfMissingOut: 0.
|
|
2361
|
+
fearOfMissingOut: 0.2, // Low - not driven by urgency
|
|
1843
2362
|
socialProofSensitivity: 0.7, // High - relies on family advice
|
|
1844
|
-
|
|
1845
|
-
siteFamiliarity: 0.2, // Low - forgets between visits
|
|
2363
|
+
mentalModelFlexibility: 0.15, // Very low - rigid, struggles
|
|
1846
2364
|
},
|
|
1847
2365
|
},
|
|
1848
2366
|
"color-blind-deuteranopia": {
|
|
@@ -1900,31 +2418,46 @@ export const ACCESSIBILITY_PERSONAS = {
|
|
|
1900
2418
|
cognitiveTraits: {
|
|
1901
2419
|
patience: 0.6, // Accustomed to extra verification
|
|
1902
2420
|
persistence: 0.7, // Used to working around color issues
|
|
1903
|
-
|
|
2421
|
+
// Low = only clicks the obvious. A control whose state is colour-coded is
|
|
2422
|
+
// ambiguous, so the unambiguous one is chosen.
|
|
2423
|
+
riskTolerance: 0.4,
|
|
1904
2424
|
resilience: 0.7, // High - adapted to workarounds, recovers quickly (BRS)
|
|
1905
|
-
|
|
2425
|
+
// Deliberately ABOVE neutral. Deuteranopia is lifelong, common (about 8%
|
|
2426
|
+
// of men of Northern European descent) and compensated from childhood; it
|
|
2427
|
+
// is a perceptual difference, not a confidence deficit, and modelling it
|
|
2428
|
+
// as one would be wrong.
|
|
2429
|
+
selfEfficacy: 0.65,
|
|
1906
2430
|
satisficing: 0.5, // Medium - needs extra verification (Simon)
|
|
1907
|
-
|
|
2431
|
+
// Low = sceptical. Interfaces routinely signal validity and error through
|
|
2432
|
+
// colour alone, so a page's own status signals are not reliably readable
|
|
2433
|
+
// and get verified rather than believed.
|
|
2434
|
+
trustCalibration: 0.4,
|
|
1908
2435
|
interruptRecovery: 0.6, // Medium-high - good adaptation, unaffected cognition (Mark)
|
|
1909
2436
|
// New traits (v15.0.0)
|
|
1910
2437
|
comprehension: 0.7,
|
|
1911
|
-
curiosity: 0.
|
|
2438
|
+
curiosity: 0.6,
|
|
1912
2439
|
workingMemory: 0.7,
|
|
1913
2440
|
readingTendency: 0.7, // Relies on text labels
|
|
1914
|
-
|
|
1915
|
-
|
|
2441
|
+
// Scent-following depends on non-colour cues -- position, label, icon --
|
|
2442
|
+
// which is a learned and efficient strategy.
|
|
2443
|
+
informationForaging: 0.65,
|
|
2444
|
+
// High = misses changes. A state change signalled by colour alone -- a
|
|
2445
|
+
// green valid border, a red error border -- is invisible without a second
|
|
2446
|
+
// cue (MDPI 13/2/53; simulated-interface study).
|
|
2447
|
+
changeBlindness: 0.7,
|
|
1916
2448
|
anchoringBias: 0.5,
|
|
1917
2449
|
timeHorizon: 0.5,
|
|
1918
2450
|
attributionStyle: 0.3, // Blames poor design, not self
|
|
1919
|
-
|
|
2451
|
+
// Compensation is deliberate: read the label, look for the icon, re-check
|
|
2452
|
+
// the text rather than trusting the hue.
|
|
2453
|
+
metacognitivePlanning: 0.7,
|
|
1920
2454
|
proceduralFluency: 0.7, // Good with non-color cues
|
|
1921
2455
|
transferLearning: 0.7, // Recognizes non-color patterns
|
|
1922
2456
|
authoritySensitivity: 0.5,
|
|
1923
2457
|
emotionalContagion: 0.5,
|
|
1924
2458
|
fearOfMissingOut: 0.4,
|
|
1925
2459
|
socialProofSensitivity: 0.5,
|
|
1926
|
-
|
|
1927
|
-
siteFamiliarity: 0.6, // Medium-high - functional user
|
|
2460
|
+
mentalModelFlexibility: 0.65, // Adapts with workarounds
|
|
1928
2461
|
},
|
|
1929
2462
|
},
|
|
1930
2463
|
// =========================================================================
|
|
@@ -2013,8 +2546,7 @@ export const ACCESSIBILITY_PERSONAS = {
|
|
|
2013
2546
|
emotionalContagion: 0.3, // Low - less influenced by emotional UI tone
|
|
2014
2547
|
fearOfMissingOut: 0.2, // Low - not driven by social urgency
|
|
2015
2548
|
socialProofSensitivity: 0.25, // Low - evaluates independently
|
|
2016
|
-
|
|
2017
|
-
siteFamiliarity: 0.4, // Low-medium - remembers structure but needs consistency
|
|
2549
|
+
mentalModelFlexibility: 0.2, // Very low (rigid) - needs consistent patterns
|
|
2018
2550
|
},
|
|
2019
2551
|
},
|
|
2020
2552
|
"intellectual-disability": {
|
|
@@ -2100,8 +2632,7 @@ export const ACCESSIBILITY_PERSONAS = {
|
|
|
2100
2632
|
emotionalContagion: 0.7, // High - influenced by UI emotional tone
|
|
2101
2633
|
fearOfMissingOut: 0.3, // Low - not driven by urgency
|
|
2102
2634
|
socialProofSensitivity: 0.6, // Medium - influenced by social cues
|
|
2103
|
-
|
|
2104
|
-
siteFamiliarity: 0.15, // Very low - limited retention between visits
|
|
2635
|
+
mentalModelFlexibility: 0.1, // Extremely rigid - needs consistency
|
|
2105
2636
|
},
|
|
2106
2637
|
},
|
|
2107
2638
|
"aphasia-receptive": {
|
|
@@ -2186,8 +2717,7 @@ export const ACCESSIBILITY_PERSONAS = {
|
|
|
2186
2717
|
emotionalContagion: 0.5,
|
|
2187
2718
|
fearOfMissingOut: 0.3,
|
|
2188
2719
|
socialProofSensitivity: 0.4,
|
|
2189
|
-
|
|
2190
|
-
siteFamiliarity: 0.25, // Low - text-based nav makes sites feel unfamiliar each visit
|
|
2720
|
+
mentalModelFlexibility: 0.4, // Medium - adapts visually, not linguistically
|
|
2191
2721
|
},
|
|
2192
2722
|
},
|
|
2193
2723
|
"dyscalculia": {
|
|
@@ -2249,32 +2779,54 @@ export const ACCESSIBILITY_PERSONAS = {
|
|
|
2249
2779
|
fatigueSusceptibility: 0.4, // Moderate - number-heavy pages are tiring
|
|
2250
2780
|
},
|
|
2251
2781
|
cognitiveTraits: {
|
|
2252
|
-
|
|
2782
|
+
// Working memory underpins number processing, and math anxiety reduces WM
|
|
2783
|
+
// capacity further -- the two compound (PMC8946289, numerical activities
|
|
2784
|
+
// of daily living).
|
|
2785
|
+
workingMemory: 0.35,
|
|
2253
2786
|
patience: 0.5, // Medium - frustrated by numbers, fine otherwise
|
|
2254
2787
|
persistence: 0.6, // Medium-high - persistent on non-numerical tasks
|
|
2255
2788
|
curiosity: 0.6, // Normal - explores freely until numbers appear
|
|
2256
2789
|
riskTolerance: 0.4, // Low-medium - cautious with purchases/quantities
|
|
2257
2790
|
readingTendency: 0.65, // Medium-high - reads text normally, skips number-heavy sections
|
|
2258
2791
|
comprehension: 0.65, // Normal for text, low for numerical content
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2792
|
+
// Math anxiety is documented as intense and self-reinforcing: errors raise
|
|
2793
|
+
// anxiety, which lowers WM, which produces more errors.
|
|
2794
|
+
resilience: 0.35,
|
|
2795
|
+
// Years of number-task failure produce intense anxiety around bills,
|
|
2796
|
+
// budgeting and any quantity judgement.
|
|
2797
|
+
selfEfficacy: 0.3,
|
|
2798
|
+
// High = takes the first adequate option. Comparison shopping means
|
|
2799
|
+
// comparing numbers, which is the expensive operation.
|
|
2800
|
+
satisficing: 0.75,
|
|
2801
|
+
// High = trusting. A displayed total cannot be sanity-checked mentally, so
|
|
2802
|
+
// it has to be taken on faith.
|
|
2803
|
+
trustCalibration: 0.65,
|
|
2263
2804
|
interruptRecovery: 0.6, // Normal
|
|
2264
2805
|
informationForaging: 0.55, // Medium - normal except for numerical scent
|
|
2265
2806
|
changeBlindness: 0.5, // Normal
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2807
|
+
// High = the first number dominates. Unable to evaluate quantities
|
|
2808
|
+
// independently, the first price or figure seen becomes the reference.
|
|
2809
|
+
anchoringBias: 0.75,
|
|
2810
|
+
// High = present-focused. Difficulty judging time and distance is a core
|
|
2811
|
+
// symptom, so future consequences are hard to weigh against an immediate
|
|
2812
|
+
// task.
|
|
2813
|
+
timeHorizon: 0.75,
|
|
2814
|
+
// High = blames self. Numeric failure is culturally read as personal
|
|
2815
|
+
// deficiency rather than a processing difference, so self-attribution runs
|
|
2816
|
+
// high.
|
|
2817
|
+
attributionStyle: 0.7,
|
|
2818
|
+
// Adults describe deliberate workarounds: calculators, written steps,
|
|
2819
|
+
// avoiding mental arithmetic. That is planned strategy, not reflex.
|
|
2820
|
+
metacognitivePlanning: 0.65,
|
|
2821
|
+
// Multi-step numeric flows -- quantities, totals, percentages, dates --
|
|
2822
|
+
// are exactly where slow and error-prone processing bites.
|
|
2823
|
+
proceduralFluency: 0.4,
|
|
2271
2824
|
transferLearning: 0.6, // Normal for non-numerical patterns
|
|
2272
2825
|
authoritySensitivity: 0.5,
|
|
2273
2826
|
emotionalContagion: 0.5,
|
|
2274
2827
|
fearOfMissingOut: 0.5,
|
|
2275
2828
|
socialProofSensitivity: 0.5,
|
|
2276
|
-
|
|
2277
|
-
siteFamiliarity: 0.5, // Medium - normal retention
|
|
2829
|
+
mentalModelFlexibility: 0.6, // Medium - adapts well to non-numerical patterns
|
|
2278
2830
|
},
|
|
2279
2831
|
},
|
|
2280
2832
|
};
|
|
@@ -2350,33 +2902,32 @@ export const EMOTIONAL_PERSONAS = {
|
|
|
2350
2902
|
},
|
|
2351
2903
|
},
|
|
2352
2904
|
cognitiveTraits: {
|
|
2353
|
-
patience: 0.
|
|
2354
|
-
riskTolerance: 0.
|
|
2905
|
+
patience: 0.8, // Low - anxiety makes waiting feel worse
|
|
2906
|
+
riskTolerance: 0.2, // Very low - avoids uncertain outcomes
|
|
2355
2907
|
comprehension: 0.6, // Medium - understands but worries
|
|
2356
|
-
persistence: 0.
|
|
2908
|
+
persistence: 0.6, // Low-medium - gives up when anxious
|
|
2357
2909
|
curiosity: 0.3, // Low - prefers safe known paths
|
|
2358
2910
|
workingMemory: 0.5, // Medium - anxiety can impair WM
|
|
2359
|
-
readingTendency: 0.
|
|
2360
|
-
resilience: 0.
|
|
2361
|
-
selfEfficacy: 0.
|
|
2362
|
-
satisficing: 0.
|
|
2363
|
-
trustCalibration: 0.
|
|
2364
|
-
interruptRecovery: 0.
|
|
2911
|
+
readingTendency: 0.9, // High - reads everything for reassurance
|
|
2912
|
+
resilience: 0.3, // Very low - slow emotional recovery
|
|
2913
|
+
selfEfficacy: 0.3, // Very low - doubts own abilities
|
|
2914
|
+
satisficing: 0.3, // Low-medium - wants certainty
|
|
2915
|
+
trustCalibration: 0.2, // Low - skeptical and worried
|
|
2916
|
+
interruptRecovery: 0.4, // Low - anxiety compounds on interruption
|
|
2365
2917
|
// New traits (v15.0.0)
|
|
2366
2918
|
informationForaging: 0.4, // Low - overthinks each path
|
|
2367
2919
|
changeBlindness: 0.3, // Low - hypervigilant, notices changes
|
|
2368
2920
|
anchoringBias: 0.7, // High - sticks to first safe option
|
|
2369
2921
|
timeHorizon: 0.3, // Long-term - worries about consequences
|
|
2370
|
-
attributionStyle: 0.
|
|
2922
|
+
attributionStyle: 0.7, // Very high - blames self for everything
|
|
2371
2923
|
metacognitivePlanning: 0.6, // Medium-high - plans to avoid anxiety
|
|
2372
2924
|
proceduralFluency: 0.5, // Medium - follows carefully
|
|
2373
|
-
transferLearning: 0.
|
|
2925
|
+
transferLearning: 0.4, // Medium
|
|
2374
2926
|
authoritySensitivity: 0.7, // High - seeks reassurance from authority
|
|
2375
|
-
emotionalContagion: 0.
|
|
2927
|
+
emotionalContagion: 0.7, // Very high - absorbs UI emotional tone
|
|
2376
2928
|
fearOfMissingOut: 0.6, // Medium-high - anxiety about missing out
|
|
2377
|
-
socialProofSensitivity: 0.
|
|
2378
|
-
|
|
2379
|
-
siteFamiliarity: 0.5, // Medium
|
|
2929
|
+
socialProofSensitivity: 0.8, // High - seeks validation from others
|
|
2930
|
+
mentalModelFlexibility: 0.4, // Low-medium - struggles with unexpected
|
|
2380
2931
|
},
|
|
2381
2932
|
context: {
|
|
2382
2933
|
viewport: [1280, 800],
|
|
@@ -2428,33 +2979,32 @@ export const EMOTIONAL_PERSONAS = {
|
|
|
2428
2979
|
},
|
|
2429
2980
|
},
|
|
2430
2981
|
cognitiveTraits: {
|
|
2431
|
-
patience: 0.
|
|
2982
|
+
patience: 0.3, // Medium - not impatient but efficient
|
|
2432
2983
|
riskTolerance: 0.8, // High - willing to try things
|
|
2433
2984
|
comprehension: 0.7, // High - understands quickly
|
|
2434
|
-
persistence: 0.
|
|
2985
|
+
persistence: 0.7, // High - doesn't give up easily
|
|
2435
2986
|
curiosity: 0.6, // Medium-high - willing to explore
|
|
2436
2987
|
workingMemory: 0.7, // High - focused and clear
|
|
2437
|
-
readingTendency: 0.
|
|
2438
|
-
resilience: 0.
|
|
2988
|
+
readingTendency: 0.2, // Low - scans efficiently
|
|
2989
|
+
resilience: 0.8, // Very high - bounces back immediately
|
|
2439
2990
|
selfEfficacy: 0.9, // Very high - trusts own abilities
|
|
2440
|
-
satisficing: 0.
|
|
2991
|
+
satisficing: 0.7, // Medium - balances speed and quality
|
|
2441
2992
|
trustCalibration: 0.7, // High - appropriate trust
|
|
2442
|
-
interruptRecovery: 0.
|
|
2993
|
+
interruptRecovery: 0.7, // High - resumes easily
|
|
2443
2994
|
// New traits (v15.0.0)
|
|
2444
2995
|
informationForaging: 0.8, // High - efficient scent-following
|
|
2445
|
-
changeBlindness: 0.
|
|
2996
|
+
changeBlindness: 0.6, // Low - notices changes
|
|
2446
2997
|
anchoringBias: 0.3, // Low - evaluates options freely
|
|
2447
2998
|
timeHorizon: 0.4, // Medium-long - thinks ahead
|
|
2448
2999
|
attributionStyle: 0.2, // Low - blames system issues
|
|
2449
|
-
metacognitivePlanning: 0.
|
|
2450
|
-
proceduralFluency: 0.
|
|
2451
|
-
transferLearning: 0.
|
|
2452
|
-
authoritySensitivity: 0.
|
|
2453
|
-
emotionalContagion: 0.
|
|
3000
|
+
metacognitivePlanning: 0.4, // High - plans efficiently
|
|
3001
|
+
proceduralFluency: 0.7, // High - follows procedures well
|
|
3002
|
+
transferLearning: 0.8, // High - applies knowledge
|
|
3003
|
+
authoritySensitivity: 0.3, // Low-medium - independent judgment
|
|
3004
|
+
emotionalContagion: 0.3, // Low - emotionally stable
|
|
2454
3005
|
fearOfMissingOut: 0.3, // Low - not swayed by urgency
|
|
2455
|
-
socialProofSensitivity: 0.
|
|
2456
|
-
|
|
2457
|
-
siteFamiliarity: 0.5, // Medium
|
|
3006
|
+
socialProofSensitivity: 0.3, // Low-medium - evaluates on merits
|
|
3007
|
+
mentalModelFlexibility: 0.8, // High - adapts easily
|
|
2458
3008
|
},
|
|
2459
3009
|
context: {
|
|
2460
3010
|
viewport: [1920, 1080],
|
|
@@ -2511,28 +3061,27 @@ export const EMOTIONAL_PERSONAS = {
|
|
|
2511
3061
|
comprehension: 0.5, // Medium
|
|
2512
3062
|
persistence: 0.4, // Low-medium - gives up when frustrated
|
|
2513
3063
|
curiosity: 0.6, // Medium-high - excitement drives exploration
|
|
2514
|
-
workingMemory: 0.
|
|
2515
|
-
readingTendency: 0.
|
|
2516
|
-
resilience: 0.
|
|
3064
|
+
workingMemory: 0.5, // Medium - emotions can interfere
|
|
3065
|
+
readingTendency: 0.6, // Medium
|
|
3066
|
+
resilience: 0.4, // Very low - emotions linger long
|
|
2517
3067
|
selfEfficacy: 0.5, // Medium - mood dependent
|
|
2518
3068
|
satisficing: 0.6, // Medium-high - wants quick resolution
|
|
2519
3069
|
trustCalibration: 0.5, // Medium - emotional judgment
|
|
2520
|
-
interruptRecovery: 0.
|
|
3070
|
+
interruptRecovery: 0.4, // Low - emotional state persists
|
|
2521
3071
|
// New traits (v15.0.0)
|
|
2522
3072
|
informationForaging: 0.5, // Medium - mood dependent
|
|
2523
3073
|
changeBlindness: 0.5, // Medium - emotions distract
|
|
2524
|
-
anchoringBias: 0.
|
|
3074
|
+
anchoringBias: 0.7, // Medium-high - first impressions stick
|
|
2525
3075
|
timeHorizon: 0.7, // Short-term - emotional decisions
|
|
2526
3076
|
attributionStyle: 0.5, // Medium - variable based on mood
|
|
2527
|
-
metacognitivePlanning: 0.
|
|
2528
|
-
proceduralFluency: 0.
|
|
3077
|
+
metacognitivePlanning: 0.4, // Low - emotional impulsivity
|
|
3078
|
+
proceduralFluency: 0.5, // Medium - emotions interfere
|
|
2529
3079
|
transferLearning: 0.5, // Medium
|
|
2530
3080
|
authoritySensitivity: 0.5, // Medium - mood dependent
|
|
2531
3081
|
emotionalContagion: 0.9, // Maximum - highly influenced by UI tone
|
|
2532
|
-
fearOfMissingOut: 0.
|
|
2533
|
-
socialProofSensitivity: 0.
|
|
2534
|
-
|
|
2535
|
-
siteFamiliarity: 0.5, // Medium
|
|
3082
|
+
fearOfMissingOut: 0.7, // High - emotional FOMO
|
|
3083
|
+
socialProofSensitivity: 0.8, // High - seeks emotional validation
|
|
3084
|
+
mentalModelFlexibility: 0.5, // Medium
|
|
2536
3085
|
},
|
|
2537
3086
|
context: {
|
|
2538
3087
|
viewport: [1280, 800],
|
|
@@ -2584,33 +3133,32 @@ export const EMOTIONAL_PERSONAS = {
|
|
|
2584
3133
|
},
|
|
2585
3134
|
},
|
|
2586
3135
|
cognitiveTraits: {
|
|
2587
|
-
patience: 0.
|
|
3136
|
+
patience: 0.7, // Very high - doesn't rush
|
|
2588
3137
|
riskTolerance: 0.5, // Medium - balanced judgment
|
|
2589
3138
|
comprehension: 0.7, // High - clear thinking
|
|
2590
|
-
persistence: 0.
|
|
3139
|
+
persistence: 0.7, // Very high - never gives up
|
|
2591
3140
|
curiosity: 0.4, // Medium - methodical exploration
|
|
2592
|
-
workingMemory: 0.
|
|
2593
|
-
readingTendency: 0.
|
|
2594
|
-
resilience: 0.
|
|
2595
|
-
selfEfficacy: 0.
|
|
3141
|
+
workingMemory: 0.7, // High - unaffected by emotion
|
|
3142
|
+
readingTendency: 0.7, // Medium-high - thorough
|
|
3143
|
+
resilience: 0.8, // Maximum - emotions barely register
|
|
3144
|
+
selfEfficacy: 0.6, // High - quiet confidence
|
|
2596
3145
|
satisficing: 0.4, // Low - willing to be thorough
|
|
2597
|
-
trustCalibration: 0.
|
|
2598
|
-
interruptRecovery: 0.
|
|
3146
|
+
trustCalibration: 0.7, // Medium-high - rational evaluation
|
|
3147
|
+
interruptRecovery: 0.7, // High - returns to task easily
|
|
2599
3148
|
// New traits (v15.0.0)
|
|
2600
|
-
informationForaging: 0.
|
|
2601
|
-
changeBlindness: 0.
|
|
3149
|
+
informationForaging: 0.8, // Medium-high - methodical
|
|
3150
|
+
changeBlindness: 0.4, // Low - attentive, focused
|
|
2602
3151
|
anchoringBias: 0.3, // Low - evaluates all options
|
|
2603
3152
|
timeHorizon: 0.2, // Very long-term - patient deliberation
|
|
2604
3153
|
attributionStyle: 0.4, // Medium - balanced evaluation
|
|
2605
|
-
metacognitivePlanning: 0.
|
|
2606
|
-
proceduralFluency: 0.
|
|
3154
|
+
metacognitivePlanning: 0.7, // High - plans carefully
|
|
3155
|
+
proceduralFluency: 0.6, // High - follows procedures precisely
|
|
2607
3156
|
transferLearning: 0.7, // High - applies experience
|
|
2608
3157
|
authoritySensitivity: 0.4, // Low-medium - independent judgment
|
|
2609
|
-
emotionalContagion: 0.
|
|
2610
|
-
fearOfMissingOut: 0.
|
|
2611
|
-
socialProofSensitivity: 0.
|
|
2612
|
-
|
|
2613
|
-
siteFamiliarity: 0.5, // Medium
|
|
3158
|
+
emotionalContagion: 0.2, // Minimum - emotionally unaffected
|
|
3159
|
+
fearOfMissingOut: 0.2, // Minimum - not driven by urgency
|
|
3160
|
+
socialProofSensitivity: 0.4, // Low - evaluates independently
|
|
3161
|
+
mentalModelFlexibility: 0.7, // High - adapts methodically
|
|
2614
3162
|
},
|
|
2615
3163
|
context: {
|
|
2616
3164
|
viewport: [1280, 800],
|
|
@@ -2646,6 +3194,30 @@ export function listEmotionalPersonas() {
|
|
|
2646
3194
|
* @param name Persona name to look up
|
|
2647
3195
|
* @returns Persona object or undefined if not found
|
|
2648
3196
|
*/
|
|
3197
|
+
/**
|
|
3198
|
+
* Resolve a persona name tolerantly: case and punctuation do not have to match.
|
|
3199
|
+
*
|
|
3200
|
+
* Resolution was exact-match only, so "POWER-USER" and "power user" both missed
|
|
3201
|
+
* a persona that plainly exists. Before unknown names started throwing, a miss
|
|
3202
|
+
* silently fabricated an all-midpoint persona named after whatever string was
|
|
3203
|
+
* passed -- so a caller who capitalised a name got clean, plausible, invented
|
|
3204
|
+
* data. Now it throws, which is better but still refuses a request anyone would
|
|
3205
|
+
* call valid.
|
|
3206
|
+
*
|
|
3207
|
+
* Exact match is tried FIRST and always wins, so this can only ever add
|
|
3208
|
+
* resolutions, never redirect one that already worked. (2026-08-02)
|
|
3209
|
+
*/
|
|
3210
|
+
function resolveLoosely(name) {
|
|
3211
|
+
const norm = (v) => v.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
3212
|
+
const target = norm(name);
|
|
3213
|
+
if (!target)
|
|
3214
|
+
return undefined;
|
|
3215
|
+
for (const key of listAllPersonas()) {
|
|
3216
|
+
if (norm(key) === target)
|
|
3217
|
+
return key;
|
|
3218
|
+
}
|
|
3219
|
+
return undefined;
|
|
3220
|
+
}
|
|
2649
3221
|
export function getAnyPersona(name) {
|
|
2650
3222
|
// 1. Check runtime-registered personas first (Enterprise extensions)
|
|
2651
3223
|
if (RUNTIME_PERSONAS[name]) {
|
|
@@ -2672,6 +3244,11 @@ export function getAnyPersona(name) {
|
|
|
2672
3244
|
if (AGENT_PERSONAS[name]) {
|
|
2673
3245
|
return AGENT_PERSONAS[name];
|
|
2674
3246
|
}
|
|
3247
|
+
// Exact match failed. Try again ignoring case and punctuation -- only after
|
|
3248
|
+
// every exact lookup above has missed, so this can never shadow a real key.
|
|
3249
|
+
const loose = resolveLoosely(name);
|
|
3250
|
+
if (loose && loose !== name)
|
|
3251
|
+
return getAnyPersona(loose);
|
|
2675
3252
|
return undefined;
|
|
2676
3253
|
}
|
|
2677
3254
|
/**
|
|
@@ -2679,6 +3256,90 @@ export function getAnyPersona(name) {
|
|
|
2679
3256
|
*
|
|
2680
3257
|
* @returns Combined list of all available persona names
|
|
2681
3258
|
*/
|
|
3259
|
+
/**
|
|
3260
|
+
* Raised when a persona name resolves to nothing.
|
|
3261
|
+
*
|
|
3262
|
+
* A distinct class so callers can tell "you asked for someone who does not
|
|
3263
|
+
* exist" apart from "the page would not load", and so the message can carry
|
|
3264
|
+
* suggestions instead of a bare failure.
|
|
3265
|
+
*/
|
|
3266
|
+
export class UnknownPersonaError extends Error {
|
|
3267
|
+
requested;
|
|
3268
|
+
suggestions;
|
|
3269
|
+
code = "unknown_persona";
|
|
3270
|
+
constructor(requested, suggestions) {
|
|
3271
|
+
super(`Unknown persona "${requested}".` +
|
|
3272
|
+
(suggestions.length ? ` Did you mean: ${suggestions.join(", ")}?` : "") +
|
|
3273
|
+
` Run list_cognitive_personas for the full roster. Nothing was measured — a persona that does not exist cannot be simulated.`);
|
|
3274
|
+
this.requested = requested;
|
|
3275
|
+
this.suggestions = suggestions;
|
|
3276
|
+
this.name = "UnknownPersonaError";
|
|
3277
|
+
}
|
|
3278
|
+
}
|
|
3279
|
+
/** Closest roster names to a miss, for the error message. */
|
|
3280
|
+
export function suggestPersonaNames(requested, limit = 3) {
|
|
3281
|
+
const roster = listAllPersonas();
|
|
3282
|
+
const q = requested.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
3283
|
+
if (!q)
|
|
3284
|
+
return roster.slice(0, limit);
|
|
3285
|
+
const scored = roster.map((name) => {
|
|
3286
|
+
const n = name.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
3287
|
+
// Exact-after-normalising ranks first: it catches the case and punctuation
|
|
3288
|
+
// misses ("POWER-USER", "power user") that are the commonest way to miss.
|
|
3289
|
+
if (n === q)
|
|
3290
|
+
return { name, score: 0 };
|
|
3291
|
+
if (n.startsWith(q) || q.startsWith(n))
|
|
3292
|
+
return { name, score: 1 };
|
|
3293
|
+
if (n.includes(q) || q.includes(n))
|
|
3294
|
+
return { name, score: 2 };
|
|
3295
|
+
// Cheap edit distance, bounded — the roster is small enough that an exact
|
|
3296
|
+
// Levenshtein is affordable and a typo is the other common miss.
|
|
3297
|
+
const d = (a, b) => {
|
|
3298
|
+
const prev = Array.from({ length: b.length + 1 }, (_, i) => i);
|
|
3299
|
+
for (let i = 1; i <= a.length; i++) {
|
|
3300
|
+
let last = prev[0];
|
|
3301
|
+
prev[0] = i;
|
|
3302
|
+
for (let j = 1; j <= b.length; j++) {
|
|
3303
|
+
const tmp = prev[j];
|
|
3304
|
+
prev[j] = Math.min(prev[j] + 1, prev[j - 1] + 1, last + (a[i - 1] === b[j - 1] ? 0 : 1));
|
|
3305
|
+
last = tmp;
|
|
3306
|
+
}
|
|
3307
|
+
}
|
|
3308
|
+
return prev[b.length];
|
|
3309
|
+
};
|
|
3310
|
+
return { name, score: 3 + d(q, n) };
|
|
3311
|
+
});
|
|
3312
|
+
return scored.sort((a, b) => a.score - b.score).filter((x) => x.score < 3 + Math.max(4, q.length * 0.5))
|
|
3313
|
+
.slice(0, limit).map((x) => x.name);
|
|
3314
|
+
}
|
|
3315
|
+
/**
|
|
3316
|
+
* Resolve a persona name, or refuse.
|
|
3317
|
+
*
|
|
3318
|
+
* Every persona-accepting tool used to fall back to
|
|
3319
|
+
* `createCognitivePersona(name, name, {})` on a miss, which builds a complete
|
|
3320
|
+
* persona with every trait at its 0.5 default and names it after whatever
|
|
3321
|
+
* string was passed. The result was a full six-layer breakdown, an abandonment
|
|
3322
|
+
* risk, a rendered motor overlay and an interpretation sentence quoting the
|
|
3323
|
+
* typo as if it were a subject — in range, plausible, and indistinguishable
|
|
3324
|
+
* from a real measurement at analysis time.
|
|
3325
|
+
*
|
|
3326
|
+
* That is silent data corruption: it does not fail, it lies quietly, and a
|
|
3327
|
+
* typo inside a batch run enters a results table having passed eyeballing and
|
|
3328
|
+
* range checks. So a miss now throws.
|
|
3329
|
+
*
|
|
3330
|
+
* `syntheticTraits` is the one legitimate synthesis: a caller defining an
|
|
3331
|
+
* ad-hoc persona by supplying its traits outright. Supplying NO traits and no
|
|
3332
|
+
* known name is not defining a persona, it is a typo. (2026-08-02)
|
|
3333
|
+
*/
|
|
3334
|
+
export function resolvePersonaOrThrow(name, syntheticTraits) {
|
|
3335
|
+
const found = getAnyPersona(name);
|
|
3336
|
+
if (found)
|
|
3337
|
+
return found;
|
|
3338
|
+
if (syntheticTraits && Object.keys(syntheticTraits).length > 0) {
|
|
3339
|
+
return createCognitivePersona(name, name, syntheticTraits);
|
|
3340
|
+
}
|
|
3341
|
+
throw new UnknownPersonaError(name, suggestPersonaNames(name));
|
|
3342
|
+
}
|
|
2682
3343
|
export function listAllPersonas() {
|
|
2683
3344
|
const runtimeNames = Object.keys(RUNTIME_PERSONAS);
|
|
2684
3345
|
const builtinNames = Object.keys(BUILTIN_PERSONAS);
|