cbrowser 16.10.0 → 16.14.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/README.md +32 -0
- package/dist/analysis/chaos-testing.d.ts.map +1 -1
- package/dist/analysis/chaos-testing.js +8 -1
- package/dist/analysis/chaos-testing.js.map +1 -1
- package/dist/browser.d.ts +8 -0
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +144 -1
- package/dist/browser.js.map +1 -1
- package/dist/cli.js +3 -2
- package/dist/cli.js.map +1 -1
- package/dist/mcp-server-remote.d.ts.map +1 -1
- package/dist/mcp-server-remote.js +475 -34
- package/dist/mcp-server-remote.js.map +1 -1
- package/dist/mcp-server.d.ts.map +1 -1
- package/dist/mcp-server.js +519 -33
- package/dist/mcp-server.js.map +1 -1
- package/dist/performance/metrics.d.ts +2 -2
- package/dist/performance/metrics.d.ts.map +1 -1
- package/dist/performance/metrics.js +37 -1
- package/dist/performance/metrics.js.map +1 -1
- package/dist/persona-questionnaire.d.ts +142 -1
- package/dist/persona-questionnaire.d.ts.map +1 -1
- package/dist/persona-questionnaire.js +581 -34
- package/dist/persona-questionnaire.js.map +1 -1
- package/dist/types.d.ts +2 -2
- package/dist/types.d.ts.map +1 -1
- package/dist/values/persona-values.d.ts +5 -0
- package/dist/values/persona-values.d.ts.map +1 -1
- package/dist/values/persona-values.js +79 -38
- package/dist/values/persona-values.js.map +1 -1
- package/dist/visual/cross-browser.d.ts.map +1 -1
- package/dist/visual/cross-browser.js +10 -1
- package/dist/visual/cross-browser.js.map +1 -1
- package/docs/personas/Persona-Index.md +126 -0
- package/docs/research/Values-Research.md +426 -0
- package/package.json +1 -1
|
@@ -49,13 +49,15 @@ import { runNLTestSuite, parseNLTestSuite, dryRunNLTestSuite, repairTest, detect
|
|
|
49
49
|
// Analysis module imports
|
|
50
50
|
import { huntBugs, runChaosTest, comparePersonas, findElementByIntent, runAgentReadyAudit, runCompetitiveBenchmark, runEmpathyAudit, } from "./analysis/index.js";
|
|
51
51
|
// Accessibility personas for empathy audit
|
|
52
|
-
import { listAccessibilityPersonas } from "./personas.js";
|
|
52
|
+
import { listAccessibilityPersonas, getAccessibilityPersona } from "./personas.js";
|
|
53
53
|
// Persona imports for cognitive journey
|
|
54
54
|
import { getPersona, listPersonas, getCognitiveProfile, createCognitivePersona, } from "./personas.js";
|
|
55
55
|
// Import API key check for bridge workflow detection
|
|
56
56
|
import { isApiKeyConfigured } from "./cognitive/index.js";
|
|
57
57
|
// Performance module imports
|
|
58
58
|
import { capturePerformanceBaseline, detectPerformanceRegression, listPerformanceBaselines, } from "./performance/index.js";
|
|
59
|
+
// Values system (Schwartz's 10 Universal Values)
|
|
60
|
+
import { getPersonaValues, PERSONA_VALUE_PROFILES, rankInfluencePatternsForProfile, INFLUENCE_PATTERNS, } from "./values/index.js";
|
|
59
61
|
// Version from package.json - single source of truth
|
|
60
62
|
import { VERSION } from "./version.js";
|
|
61
63
|
// Stealth/Enterprise loader (v16.2.0)
|
|
@@ -992,19 +994,56 @@ function configureMcpTools(server) {
|
|
|
992
994
|
blockUrls: z.array(z.string()).optional().describe("URL patterns to block"),
|
|
993
995
|
}, async ({ url, networkLatency, offline, blockUrls }) => {
|
|
994
996
|
const b = await getBrowser();
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
997
|
+
try {
|
|
998
|
+
const result = await runChaosTest(b, url, { networkLatency, offline, blockUrls });
|
|
999
|
+
return {
|
|
1000
|
+
content: [
|
|
1001
|
+
{
|
|
1002
|
+
type: "text",
|
|
1003
|
+
text: JSON.stringify({
|
|
1004
|
+
passed: result.passed,
|
|
1005
|
+
errors: result.errors,
|
|
1006
|
+
duration: result.duration,
|
|
1007
|
+
// v16.11.0: Include impact analysis in response
|
|
1008
|
+
impact: result.impact,
|
|
1009
|
+
}, null, 2),
|
|
1010
|
+
},
|
|
1011
|
+
],
|
|
1012
|
+
};
|
|
1013
|
+
}
|
|
1014
|
+
catch (error) {
|
|
1015
|
+
// v16.11.0: Graceful error handling for chaos test crashes
|
|
1016
|
+
// Attempt browser recovery to prevent server crash
|
|
1017
|
+
try {
|
|
1018
|
+
await b.recoverBrowser();
|
|
1019
|
+
}
|
|
1020
|
+
catch {
|
|
1021
|
+
// Browser recovery failed, but continue with error response
|
|
1022
|
+
}
|
|
1023
|
+
return {
|
|
1024
|
+
content: [
|
|
1025
|
+
{
|
|
1026
|
+
type: "text",
|
|
1027
|
+
text: JSON.stringify({
|
|
1028
|
+
passed: false,
|
|
1029
|
+
errors: [`Chaos test crashed: ${error.message}`],
|
|
1030
|
+
duration: 0,
|
|
1031
|
+
impact: {
|
|
1032
|
+
loadTimeMs: 0,
|
|
1033
|
+
blockedResources: [],
|
|
1034
|
+
failedResources: [],
|
|
1035
|
+
delayedResources: [],
|
|
1036
|
+
pageCompleted: false,
|
|
1037
|
+
pageInteractive: false,
|
|
1038
|
+
consoleErrors: 0,
|
|
1039
|
+
degradationSummary: ["Test crashed - browser recovered"],
|
|
1040
|
+
},
|
|
1041
|
+
recovered: true,
|
|
1042
|
+
}, null, 2),
|
|
1043
|
+
},
|
|
1044
|
+
],
|
|
1045
|
+
};
|
|
1046
|
+
}
|
|
1008
1047
|
});
|
|
1009
1048
|
server.tool("compare_personas", "Compare how different user personas experience a journey. In Claude Code sessions (no API key), use compare_personas_init and compare_personas_complete instead for the bridge workflow.", {
|
|
1010
1049
|
url: z.string().url().describe("Starting URL"),
|
|
@@ -1266,6 +1305,7 @@ Begin with the first persona: ${personas[0]}
|
|
|
1266
1305
|
goal: z.string().describe("What the simulated user is trying to accomplish"),
|
|
1267
1306
|
startUrl: z.string().url().describe("Starting URL for the journey"),
|
|
1268
1307
|
customTraits: z.object({
|
|
1308
|
+
// Core 7 traits
|
|
1269
1309
|
patience: z.number().min(0).max(1).optional(),
|
|
1270
1310
|
riskTolerance: z.number().min(0).max(1).optional(),
|
|
1271
1311
|
comprehension: z.number().min(0).max(1).optional(),
|
|
@@ -1273,7 +1313,26 @@ Begin with the first persona: ${personas[0]}
|
|
|
1273
1313
|
curiosity: z.number().min(0).max(1).optional(),
|
|
1274
1314
|
workingMemory: z.number().min(0).max(1).optional(),
|
|
1275
1315
|
readingTendency: z.number().min(0).max(1).optional(),
|
|
1276
|
-
|
|
1316
|
+
// v16.11.0: Extended traits (18 more = 25 total)
|
|
1317
|
+
resilience: z.number().min(0).max(1).optional(),
|
|
1318
|
+
selfEfficacy: z.number().min(0).max(1).optional(),
|
|
1319
|
+
satisficing: z.number().min(0).max(1).optional(),
|
|
1320
|
+
trustCalibration: z.number().min(0).max(1).optional(),
|
|
1321
|
+
interruptRecovery: z.number().min(0).max(1).optional(),
|
|
1322
|
+
informationForaging: z.number().min(0).max(1).optional(),
|
|
1323
|
+
changeBlindness: z.number().min(0).max(1).optional(),
|
|
1324
|
+
anchoringBias: z.number().min(0).max(1).optional(),
|
|
1325
|
+
timeHorizon: z.number().min(0).max(1).optional(),
|
|
1326
|
+
attributionStyle: z.number().min(0).max(1).optional(),
|
|
1327
|
+
metacognitivePlanning: z.number().min(0).max(1).optional(),
|
|
1328
|
+
proceduralFluency: z.number().min(0).max(1).optional(),
|
|
1329
|
+
transferLearning: z.number().min(0).max(1).optional(),
|
|
1330
|
+
authoritySensitivity: z.number().min(0).max(1).optional(),
|
|
1331
|
+
emotionalContagion: z.number().min(0).max(1).optional(),
|
|
1332
|
+
fearOfMissingOut: z.number().min(0).max(1).optional(),
|
|
1333
|
+
socialProofSensitivity: z.number().min(0).max(1).optional(),
|
|
1334
|
+
mentalModelRigidity: z.number().min(0).max(1).optional(),
|
|
1335
|
+
}).optional().describe("Override specific cognitive traits (25 available)"),
|
|
1277
1336
|
}, async ({ persona: personaName, goal, startUrl, customTraits }) => {
|
|
1278
1337
|
// Get or create persona
|
|
1279
1338
|
const existingPersona = getPersona(personaName);
|
|
@@ -1283,8 +1342,9 @@ Begin with the first persona: ${personas[0]}
|
|
|
1283
1342
|
personaObj = createCognitivePersona(personaName, personaName, customTraits || {});
|
|
1284
1343
|
}
|
|
1285
1344
|
else if (customTraits) {
|
|
1286
|
-
//
|
|
1345
|
+
// v16.11.0: Full 25-trait default set (was only 7, causing trait dropout)
|
|
1287
1346
|
const defaultTraits = {
|
|
1347
|
+
// Core 7 traits
|
|
1288
1348
|
patience: 0.5,
|
|
1289
1349
|
riskTolerance: 0.5,
|
|
1290
1350
|
comprehension: 0.5,
|
|
@@ -1292,6 +1352,26 @@ Begin with the first persona: ${personas[0]}
|
|
|
1292
1352
|
curiosity: 0.5,
|
|
1293
1353
|
workingMemory: 0.5,
|
|
1294
1354
|
readingTendency: 0.5,
|
|
1355
|
+
// Tier 1: Core (5 more)
|
|
1356
|
+
resilience: 0.5,
|
|
1357
|
+
selfEfficacy: 0.5,
|
|
1358
|
+
satisficing: 0.5,
|
|
1359
|
+
trustCalibration: 0.5,
|
|
1360
|
+
interruptRecovery: 0.5,
|
|
1361
|
+
// Tier 2-6: Extended (13 more)
|
|
1362
|
+
informationForaging: 0.5,
|
|
1363
|
+
changeBlindness: 0.3,
|
|
1364
|
+
anchoringBias: 0.5,
|
|
1365
|
+
timeHorizon: 0.5,
|
|
1366
|
+
attributionStyle: 0.5,
|
|
1367
|
+
metacognitivePlanning: 0.5,
|
|
1368
|
+
proceduralFluency: 0.5,
|
|
1369
|
+
transferLearning: 0.5,
|
|
1370
|
+
authoritySensitivity: 0.5,
|
|
1371
|
+
emotionalContagion: 0.5,
|
|
1372
|
+
fearOfMissingOut: 0.5,
|
|
1373
|
+
socialProofSensitivity: 0.5,
|
|
1374
|
+
mentalModelRigidity: 0.5,
|
|
1295
1375
|
};
|
|
1296
1376
|
personaObj = {
|
|
1297
1377
|
...existingPersona,
|
|
@@ -1337,6 +1417,11 @@ Begin with the first persona: ${personas[0]}
|
|
|
1337
1417
|
// Navigate to start URL
|
|
1338
1418
|
const b = await getBrowser();
|
|
1339
1419
|
await b.navigate(startUrl);
|
|
1420
|
+
// v16.12.0: Include persona values for influence pattern analysis
|
|
1421
|
+
const personaValues = getPersonaValues(personaObj.name);
|
|
1422
|
+
const influencePatterns = personaValues
|
|
1423
|
+
? rankInfluencePatternsForProfile(personaValues).slice(0, 5) // Top 5 most effective patterns
|
|
1424
|
+
: undefined;
|
|
1340
1425
|
return {
|
|
1341
1426
|
content: [
|
|
1342
1427
|
{
|
|
@@ -1346,6 +1431,36 @@ Begin with the first persona: ${personas[0]}
|
|
|
1346
1431
|
name: personaObj.name,
|
|
1347
1432
|
description: personaObj.description,
|
|
1348
1433
|
demographics: personaObj.demographics,
|
|
1434
|
+
values: personaValues ? {
|
|
1435
|
+
schwartz: {
|
|
1436
|
+
selfDirection: personaValues.selfDirection,
|
|
1437
|
+
stimulation: personaValues.stimulation,
|
|
1438
|
+
hedonism: personaValues.hedonism,
|
|
1439
|
+
achievement: personaValues.achievement,
|
|
1440
|
+
power: personaValues.power,
|
|
1441
|
+
security: personaValues.security,
|
|
1442
|
+
conformity: personaValues.conformity,
|
|
1443
|
+
tradition: personaValues.tradition,
|
|
1444
|
+
benevolence: personaValues.benevolence,
|
|
1445
|
+
universalism: personaValues.universalism,
|
|
1446
|
+
},
|
|
1447
|
+
higherOrder: {
|
|
1448
|
+
openness: personaValues.openness,
|
|
1449
|
+
selfEnhancement: personaValues.selfEnhancement,
|
|
1450
|
+
conservation: personaValues.conservation,
|
|
1451
|
+
selfTranscendence: personaValues.selfTranscendence,
|
|
1452
|
+
},
|
|
1453
|
+
sdt: {
|
|
1454
|
+
autonomyNeed: personaValues.autonomyNeed,
|
|
1455
|
+
competenceNeed: personaValues.competenceNeed,
|
|
1456
|
+
relatednessNeed: personaValues.relatednessNeed,
|
|
1457
|
+
},
|
|
1458
|
+
maslowLevel: personaValues.maslowLevel,
|
|
1459
|
+
} : undefined,
|
|
1460
|
+
influenceSusceptibility: influencePatterns?.map(ip => ({
|
|
1461
|
+
pattern: ip.pattern.name,
|
|
1462
|
+
susceptibility: ip.susceptibility,
|
|
1463
|
+
})),
|
|
1349
1464
|
},
|
|
1350
1465
|
cognitiveProfile: profile,
|
|
1351
1466
|
initialState,
|
|
@@ -1503,27 +1618,254 @@ Begin the simulation now. Narrate your thoughts as this persona.
|
|
|
1503
1618
|
],
|
|
1504
1619
|
};
|
|
1505
1620
|
});
|
|
1506
|
-
server.tool("list_cognitive_personas", "List all available personas with their cognitive traits", {}, async () => {
|
|
1507
|
-
|
|
1508
|
-
const
|
|
1621
|
+
server.tool("list_cognitive_personas", "List all available personas with their cognitive traits (includes accessibility and emotional personas)", {}, async () => {
|
|
1622
|
+
// v16.11.0: Include all persona types - BUILTIN + ACCESSIBILITY + EMOTIONAL
|
|
1623
|
+
const builtinNames = listPersonas();
|
|
1624
|
+
const accessibilityNames = listAccessibilityPersonas();
|
|
1625
|
+
// Built-in personas (power-user, first-timer, etc.)
|
|
1626
|
+
const builtinPersonas = builtinNames.map(name => {
|
|
1509
1627
|
const p = getPersona(name);
|
|
1510
1628
|
if (!p)
|
|
1511
1629
|
return null;
|
|
1512
1630
|
const profile = getCognitiveProfile(p);
|
|
1631
|
+
// v16.12.0: Include Schwartz values for each persona
|
|
1632
|
+
const values = getPersonaValues(p.name);
|
|
1513
1633
|
return {
|
|
1514
1634
|
name: p.name,
|
|
1515
1635
|
description: p.description,
|
|
1636
|
+
category: "builtin",
|
|
1516
1637
|
demographics: p.demographics,
|
|
1517
1638
|
cognitiveTraits: profile.traits,
|
|
1518
1639
|
attentionPattern: profile.attentionPattern,
|
|
1519
1640
|
decisionStyle: profile.decisionStyle,
|
|
1641
|
+
values: values ? {
|
|
1642
|
+
schwartz: {
|
|
1643
|
+
selfDirection: values.selfDirection,
|
|
1644
|
+
stimulation: values.stimulation,
|
|
1645
|
+
hedonism: values.hedonism,
|
|
1646
|
+
achievement: values.achievement,
|
|
1647
|
+
power: values.power,
|
|
1648
|
+
security: values.security,
|
|
1649
|
+
conformity: values.conformity,
|
|
1650
|
+
tradition: values.tradition,
|
|
1651
|
+
benevolence: values.benevolence,
|
|
1652
|
+
universalism: values.universalism,
|
|
1653
|
+
},
|
|
1654
|
+
higherOrder: {
|
|
1655
|
+
openness: values.openness,
|
|
1656
|
+
selfEnhancement: values.selfEnhancement,
|
|
1657
|
+
conservation: values.conservation,
|
|
1658
|
+
selfTranscendence: values.selfTranscendence,
|
|
1659
|
+
},
|
|
1660
|
+
sdt: {
|
|
1661
|
+
autonomyNeed: values.autonomyNeed,
|
|
1662
|
+
competenceNeed: values.competenceNeed,
|
|
1663
|
+
relatednessNeed: values.relatednessNeed,
|
|
1664
|
+
},
|
|
1665
|
+
maslowLevel: values.maslowLevel,
|
|
1666
|
+
} : undefined,
|
|
1667
|
+
};
|
|
1668
|
+
}).filter(Boolean);
|
|
1669
|
+
// Accessibility personas (motor-tremor, low-vision, adhd, etc.)
|
|
1670
|
+
const accessibilityPersonas = accessibilityNames.map(name => {
|
|
1671
|
+
const p = getAccessibilityPersona(name);
|
|
1672
|
+
if (!p)
|
|
1673
|
+
return null;
|
|
1674
|
+
// v16.11.0: Compute disabilityType and barrierTypes from accessibilityTraits
|
|
1675
|
+
const traits = p.accessibilityTraits;
|
|
1676
|
+
let disabilityType = "General accessibility";
|
|
1677
|
+
const barrierTypes = [];
|
|
1678
|
+
if (traits?.tremor) {
|
|
1679
|
+
disabilityType = "Motor impairment (tremor)";
|
|
1680
|
+
barrierTypes.push("motor_precision", "touch_target");
|
|
1681
|
+
}
|
|
1682
|
+
if (traits?.visionLevel !== undefined && traits.visionLevel < 0.5) {
|
|
1683
|
+
disabilityType = "Low vision";
|
|
1684
|
+
barrierTypes.push("visual_clarity", "contrast");
|
|
1685
|
+
}
|
|
1686
|
+
if (traits?.colorBlindness) {
|
|
1687
|
+
disabilityType = `Color blindness (${traits.colorBlindness})`;
|
|
1688
|
+
barrierTypes.push("sensory");
|
|
1689
|
+
}
|
|
1690
|
+
if (traits?.processingSpeed !== undefined && traits.processingSpeed < 0.6) {
|
|
1691
|
+
disabilityType = "Cognitive (Processing)";
|
|
1692
|
+
barrierTypes.push("cognitive_load", "temporal");
|
|
1693
|
+
}
|
|
1694
|
+
if (traits?.attentionSpan !== undefined && traits.attentionSpan < 0.5) {
|
|
1695
|
+
if (!disabilityType.includes("Cognitive")) {
|
|
1696
|
+
disabilityType = "Cognitive (ADHD/Attention)";
|
|
1697
|
+
}
|
|
1698
|
+
barrierTypes.push("cognitive_load");
|
|
1699
|
+
}
|
|
1700
|
+
// Name-based fallback
|
|
1701
|
+
if (disabilityType === "General accessibility") {
|
|
1702
|
+
if (p.name.includes("deaf") || p.name.includes("hearing"))
|
|
1703
|
+
disabilityType = "Hearing impairment";
|
|
1704
|
+
else if (p.name.includes("motor"))
|
|
1705
|
+
disabilityType = "Motor impairment";
|
|
1706
|
+
else if (p.name.includes("vision") || p.name.includes("blind"))
|
|
1707
|
+
disabilityType = "Vision impairment";
|
|
1708
|
+
else if (p.name.includes("cognitive") || p.name.includes("adhd"))
|
|
1709
|
+
disabilityType = "Cognitive";
|
|
1710
|
+
}
|
|
1711
|
+
// v16.12.0: Include Schwartz values for accessibility personas
|
|
1712
|
+
const values = getPersonaValues(p.name);
|
|
1713
|
+
return {
|
|
1714
|
+
name: p.name,
|
|
1715
|
+
description: p.description,
|
|
1716
|
+
category: "accessibility",
|
|
1717
|
+
disabilityType,
|
|
1718
|
+
demographics: p.demographics,
|
|
1719
|
+
cognitiveTraits: p.cognitiveTraits || {},
|
|
1720
|
+
barrierTypes: [...new Set(barrierTypes)], // Deduplicate
|
|
1721
|
+
values: values ? {
|
|
1722
|
+
schwartz: {
|
|
1723
|
+
selfDirection: values.selfDirection,
|
|
1724
|
+
stimulation: values.stimulation,
|
|
1725
|
+
hedonism: values.hedonism,
|
|
1726
|
+
achievement: values.achievement,
|
|
1727
|
+
power: values.power,
|
|
1728
|
+
security: values.security,
|
|
1729
|
+
conformity: values.conformity,
|
|
1730
|
+
tradition: values.tradition,
|
|
1731
|
+
benevolence: values.benevolence,
|
|
1732
|
+
universalism: values.universalism,
|
|
1733
|
+
},
|
|
1734
|
+
higherOrder: {
|
|
1735
|
+
openness: values.openness,
|
|
1736
|
+
selfEnhancement: values.selfEnhancement,
|
|
1737
|
+
conservation: values.conservation,
|
|
1738
|
+
selfTranscendence: values.selfTranscendence,
|
|
1739
|
+
},
|
|
1740
|
+
sdt: {
|
|
1741
|
+
autonomyNeed: values.autonomyNeed,
|
|
1742
|
+
competenceNeed: values.competenceNeed,
|
|
1743
|
+
relatednessNeed: values.relatednessNeed,
|
|
1744
|
+
},
|
|
1745
|
+
maslowLevel: values.maslowLevel,
|
|
1746
|
+
} : undefined,
|
|
1520
1747
|
};
|
|
1521
1748
|
}).filter(Boolean);
|
|
1749
|
+
const allPersonas = [...builtinPersonas, ...accessibilityPersonas];
|
|
1522
1750
|
return {
|
|
1523
1751
|
content: [
|
|
1524
1752
|
{
|
|
1525
1753
|
type: "text",
|
|
1526
|
-
text: JSON.stringify({
|
|
1754
|
+
text: JSON.stringify({
|
|
1755
|
+
personas: allPersonas,
|
|
1756
|
+
count: allPersonas.length,
|
|
1757
|
+
categories: {
|
|
1758
|
+
builtin: builtinPersonas.length,
|
|
1759
|
+
accessibility: accessibilityPersonas.length,
|
|
1760
|
+
},
|
|
1761
|
+
}, null, 2),
|
|
1762
|
+
},
|
|
1763
|
+
],
|
|
1764
|
+
};
|
|
1765
|
+
});
|
|
1766
|
+
// =========================================================================
|
|
1767
|
+
// Values System Tools (v16.12.0)
|
|
1768
|
+
// Schwartz's 10 Universal Values, Self-Determination Theory, Maslow
|
|
1769
|
+
// =========================================================================
|
|
1770
|
+
server.tool("persona_values_lookup", "Look up the values profile for a persona (Schwartz's 10 Universal Values, SDT needs, Maslow level). Values describe WHO the persona is at a deeper motivational level, informing influence susceptibility.", {
|
|
1771
|
+
persona: z.string().describe("Persona name (e.g., 'first-timer', 'power-user', 'anxious-user')"),
|
|
1772
|
+
includeInfluencePatterns: z.boolean().optional().default(true).describe("Include ranked influence patterns this persona is susceptible to"),
|
|
1773
|
+
}, async ({ persona, includeInfluencePatterns }) => {
|
|
1774
|
+
const values = getPersonaValues(persona);
|
|
1775
|
+
if (!values) {
|
|
1776
|
+
const availablePersonas = PERSONA_VALUE_PROFILES.map(p => p.personaName);
|
|
1777
|
+
return {
|
|
1778
|
+
content: [
|
|
1779
|
+
{
|
|
1780
|
+
type: "text",
|
|
1781
|
+
text: JSON.stringify({
|
|
1782
|
+
error: `No values profile found for persona: ${persona}`,
|
|
1783
|
+
availablePersonas,
|
|
1784
|
+
note: "Values are defined for all built-in personas. Custom personas can have values added via the questionnaire.",
|
|
1785
|
+
}, null, 2),
|
|
1786
|
+
},
|
|
1787
|
+
],
|
|
1788
|
+
};
|
|
1789
|
+
}
|
|
1790
|
+
const profile = PERSONA_VALUE_PROFILES.find(p => p.personaName.toLowerCase() === persona.toLowerCase());
|
|
1791
|
+
let influencePatterns;
|
|
1792
|
+
if (includeInfluencePatterns) {
|
|
1793
|
+
const ranked = rankInfluencePatternsForProfile(values);
|
|
1794
|
+
influencePatterns = ranked.slice(0, 7).map(r => ({
|
|
1795
|
+
pattern: r.pattern.name,
|
|
1796
|
+
susceptibility: r.susceptibility,
|
|
1797
|
+
description: r.pattern.description,
|
|
1798
|
+
}));
|
|
1799
|
+
}
|
|
1800
|
+
return {
|
|
1801
|
+
content: [
|
|
1802
|
+
{
|
|
1803
|
+
type: "text",
|
|
1804
|
+
text: JSON.stringify({
|
|
1805
|
+
persona,
|
|
1806
|
+
rationale: profile?.rationale,
|
|
1807
|
+
schwartzValues: {
|
|
1808
|
+
selfDirection: { value: values.selfDirection, meaning: "Independent thought, creativity, freedom" },
|
|
1809
|
+
stimulation: { value: values.stimulation, meaning: "Excitement, novelty, challenge" },
|
|
1810
|
+
hedonism: { value: values.hedonism, meaning: "Pleasure, sensuous gratification" },
|
|
1811
|
+
achievement: { value: values.achievement, meaning: "Personal success through competence" },
|
|
1812
|
+
power: { value: values.power, meaning: "Social status, prestige, control" },
|
|
1813
|
+
security: { value: values.security, meaning: "Safety, harmony, stability" },
|
|
1814
|
+
conformity: { value: values.conformity, meaning: "Restraint of actions that harm others" },
|
|
1815
|
+
tradition: { value: values.tradition, meaning: "Respect for customs, heritage" },
|
|
1816
|
+
benevolence: { value: values.benevolence, meaning: "Welfare of close others" },
|
|
1817
|
+
universalism: { value: values.universalism, meaning: "Tolerance, social justice, environment" },
|
|
1818
|
+
},
|
|
1819
|
+
higherOrderValues: {
|
|
1820
|
+
openness: { value: values.openness, meaning: "(selfDirection + stimulation) / 2" },
|
|
1821
|
+
selfEnhancement: { value: values.selfEnhancement, meaning: "(achievement + power) / 2" },
|
|
1822
|
+
conservation: { value: values.conservation, meaning: "(security + conformity + tradition) / 3" },
|
|
1823
|
+
selfTranscendence: { value: values.selfTranscendence, meaning: "(benevolence + universalism) / 2" },
|
|
1824
|
+
},
|
|
1825
|
+
selfDeterminationTheory: {
|
|
1826
|
+
autonomyNeed: { value: values.autonomyNeed, meaning: "Need for choice and control" },
|
|
1827
|
+
competenceNeed: { value: values.competenceNeed, meaning: "Need to feel capable" },
|
|
1828
|
+
relatednessNeed: { value: values.relatednessNeed, meaning: "Need for connection" },
|
|
1829
|
+
},
|
|
1830
|
+
maslowLevel: {
|
|
1831
|
+
level: values.maslowLevel,
|
|
1832
|
+
meaning: values.maslowLevel === "physiological" ? "Basic survival needs"
|
|
1833
|
+
: values.maslowLevel === "safety" ? "Security and stability"
|
|
1834
|
+
: values.maslowLevel === "belonging" ? "Social connection and love"
|
|
1835
|
+
: values.maslowLevel === "esteem" ? "Achievement and recognition"
|
|
1836
|
+
: "Self-fulfillment and growth",
|
|
1837
|
+
},
|
|
1838
|
+
influencePatterns,
|
|
1839
|
+
researchBasis: {
|
|
1840
|
+
schwartz: "Schwartz, S. H. (1992, 2012). Theory of Basic Human Values. DOI: 10.1016/S0065-2601(08)60281-6",
|
|
1841
|
+
sdt: "Deci, E. L., & Ryan, R. M. (1985, 2000). Self-Determination Theory. DOI: 10.1037/0003-066X.55.1.68",
|
|
1842
|
+
maslow: "Maslow, A. H. (1943). A Theory of Human Motivation. DOI: 10.1037/h0054346",
|
|
1843
|
+
},
|
|
1844
|
+
}, null, 2),
|
|
1845
|
+
},
|
|
1846
|
+
],
|
|
1847
|
+
};
|
|
1848
|
+
});
|
|
1849
|
+
server.tool("list_influence_patterns", "List all research-backed influence/persuasion patterns and which persona values make someone susceptible to each pattern. Based on Cialdini, Kahneman, and behavioral economics research.", {}, async () => {
|
|
1850
|
+
// INFLUENCE_PATTERNS is an array of InfluencePattern objects
|
|
1851
|
+
const patterns = INFLUENCE_PATTERNS.map(pattern => ({
|
|
1852
|
+
name: pattern.name,
|
|
1853
|
+
description: pattern.description,
|
|
1854
|
+
researchBasis: pattern.researchBasis,
|
|
1855
|
+
targetValues: pattern.targetValues,
|
|
1856
|
+
mechanism: pattern.mechanism,
|
|
1857
|
+
examples: pattern.examples,
|
|
1858
|
+
}));
|
|
1859
|
+
return {
|
|
1860
|
+
content: [
|
|
1861
|
+
{
|
|
1862
|
+
type: "text",
|
|
1863
|
+
text: JSON.stringify({
|
|
1864
|
+
count: patterns.length,
|
|
1865
|
+
patterns,
|
|
1866
|
+
usage: "Use persona_values_lookup to see which patterns a specific persona is susceptible to",
|
|
1867
|
+
note: "These patterns describe psychological influence mechanisms. Use ethically for UX optimization, not manipulation.",
|
|
1868
|
+
}, null, 2),
|
|
1527
1869
|
},
|
|
1528
1870
|
],
|
|
1529
1871
|
};
|
|
@@ -1532,11 +1874,12 @@ Begin the simulation now. Narrate your thoughts as this persona.
|
|
|
1532
1874
|
// Persona Questionnaire Tools (v16.5.0)
|
|
1533
1875
|
// Research-based persona generation via questionnaire
|
|
1534
1876
|
// =========================================================================
|
|
1535
|
-
server.tool("persona_questionnaire_get", "Get the persona questionnaire for building a custom persona. Returns research-backed questions that map to cognitive traits. Use comprehensive=true for all 25 traits, or leave false for 8 core traits.", {
|
|
1877
|
+
server.tool("persona_questionnaire_get", "Get the persona questionnaire for building a custom persona. Returns research-backed questions that map to cognitive traits. Use comprehensive=true for all 25 traits, or leave false for 8 core traits. v16.12.0: Now includes optional category question for disability-specific value safeguards.", {
|
|
1536
1878
|
comprehensive: z.boolean().optional().default(false).describe("Include all 25 traits (true) or just 8 core traits (false)"),
|
|
1537
1879
|
traits: z.array(z.string()).optional().describe("Specific trait names to include (overrides comprehensive)"),
|
|
1538
|
-
|
|
1539
|
-
|
|
1880
|
+
includeCategory: z.boolean().optional().default(true).describe("Include category question for disability-aware values (v16.12.0)"),
|
|
1881
|
+
}, async ({ comprehensive, traits, includeCategory }) => {
|
|
1882
|
+
const { generatePersonaQuestionnaire, formatForAskUserQuestion, CATEGORY_QUESTION } = await import("./persona-questionnaire.js");
|
|
1540
1883
|
const questions = generatePersonaQuestionnaire({
|
|
1541
1884
|
comprehensive,
|
|
1542
1885
|
traits: traits,
|
|
@@ -1547,25 +1890,39 @@ Begin the simulation now. Narrate your thoughts as this persona.
|
|
|
1547
1890
|
{
|
|
1548
1891
|
type: "text",
|
|
1549
1892
|
text: JSON.stringify({
|
|
1550
|
-
instructions: "Present these questions to the user one at a time or all at once. Each answer maps to a trait value. After collecting answers, use persona_questionnaire_build to create the persona.",
|
|
1893
|
+
instructions: "Present these questions to the user one at a time or all at once. Each answer maps to a trait value. After collecting answers, use persona_questionnaire_build to create the persona. v16.12.0: Start with the category question to enable disability-aware value safeguards.",
|
|
1551
1894
|
questionCount: questions.length,
|
|
1552
1895
|
questions: formatted,
|
|
1553
1896
|
rawQuestions: questions, // Include raw for programmatic use
|
|
1897
|
+
...(includeCategory && {
|
|
1898
|
+
categoryQuestion: CATEGORY_QUESTION,
|
|
1899
|
+
categoryInstructions: "Ask this FIRST to determine persona category. The category affects which values are applied and provides research-based safeguards for disability simulations.",
|
|
1900
|
+
}),
|
|
1554
1901
|
}, null, 2),
|
|
1555
1902
|
},
|
|
1556
1903
|
],
|
|
1557
1904
|
};
|
|
1558
1905
|
});
|
|
1559
|
-
server.tool("persona_questionnaire_build", "Build a custom persona from questionnaire answers. Answers should be a map of trait names to values (0-1). Missing traits will use intelligent defaults based on research correlations.", {
|
|
1906
|
+
server.tool("persona_questionnaire_build", "Build a custom persona from questionnaire answers with category-aware value safeguards. Answers should be a map of trait names to values (0-1). Missing traits will use intelligent defaults based on research correlations. v16.12.0: Optionally specify category for disability-specific value handling.", {
|
|
1560
1907
|
name: z.string().describe("Name for the new persona"),
|
|
1561
1908
|
description: z.string().describe("Description of the persona"),
|
|
1562
1909
|
answers: z.record(z.string(), z.number()).describe("Map of trait names to values (0-1), e.g. {patience: 0.25, riskTolerance: 0.75}"),
|
|
1910
|
+
category: z.enum(["cognitive", "physical", "sensory", "emotional", "general"]).optional().describe("Persona category for value safeguards (v16.12.0)"),
|
|
1911
|
+
valueOverrides: z.record(z.string(), z.number()).optional().describe("Override specific values (0-1) if different from category defaults"),
|
|
1563
1912
|
save: z.boolean().optional().default(true).describe("Save the persona to disk for future use"),
|
|
1564
|
-
}, async ({ name, description, answers, save }) => {
|
|
1565
|
-
const { buildTraitsFromAnswers, getTraitLabel, getTraitBehaviors } = await import("./persona-questionnaire.js");
|
|
1913
|
+
}, async ({ name, description, answers, category, valueOverrides, save }) => {
|
|
1914
|
+
const { buildTraitsFromAnswers, getTraitLabel, getTraitBehaviors, detectPersonaCategory, buildValuesFromCategory, validateCategoryValues, } = await import("./persona-questionnaire.js");
|
|
1566
1915
|
const { createCognitivePersona, saveCustomPersona } = await import("./personas.js");
|
|
1567
|
-
//
|
|
1916
|
+
// Detect or use provided category
|
|
1917
|
+
const detectedCategory = category || detectPersonaCategory(name, description);
|
|
1918
|
+
// Build traits from answers with research-based correlations (moved up for v16.14.0)
|
|
1568
1919
|
const traits = buildTraitsFromAnswers(answers);
|
|
1920
|
+
// Build category-appropriate values with optional overrides
|
|
1921
|
+
// v16.14.0: Pass traits for trait_based categories (general, emotional)
|
|
1922
|
+
const categoryResult = buildValuesFromCategory(detectedCategory, valueOverrides, traits // v16.14.0: Pass traits for trait-based value derivation
|
|
1923
|
+
);
|
|
1924
|
+
// Validate values match category guidelines
|
|
1925
|
+
const warnings = validateCategoryValues(detectedCategory, categoryResult.values);
|
|
1569
1926
|
// Create the persona
|
|
1570
1927
|
const persona = createCognitivePersona(name, description, traits, {});
|
|
1571
1928
|
// Save if requested
|
|
@@ -1597,6 +1954,19 @@ Begin the simulation now. Narrate your thoughts as this persona.
|
|
|
1597
1954
|
},
|
|
1598
1955
|
cognitiveTraits: traits,
|
|
1599
1956
|
traitSummary,
|
|
1957
|
+
// v16.12.0: Category-aware values
|
|
1958
|
+
category: {
|
|
1959
|
+
detected: detectedCategory,
|
|
1960
|
+
strategy: categoryResult.valueStrategy,
|
|
1961
|
+
guidance: categoryResult.guidance,
|
|
1962
|
+
},
|
|
1963
|
+
values: categoryResult.values,
|
|
1964
|
+
researchBasis: categoryResult.researchBasis,
|
|
1965
|
+
// v16.14.0: Show how traits influenced values for trait_based categories
|
|
1966
|
+
...(categoryResult.derivations && categoryResult.derivations.length > 0 && {
|
|
1967
|
+
valueDerivations: categoryResult.derivations,
|
|
1968
|
+
}),
|
|
1969
|
+
...(warnings.length > 0 && { warnings }),
|
|
1600
1970
|
savedPath,
|
|
1601
1971
|
usage: `Use persona "${name}" with cognitive-journey or other commands`,
|
|
1602
1972
|
}, null, 2),
|
|
@@ -1647,6 +2017,47 @@ Begin the simulation now. Narrate your thoughts as this persona.
|
|
|
1647
2017
|
],
|
|
1648
2018
|
};
|
|
1649
2019
|
});
|
|
2020
|
+
server.tool("persona_category_guidance", "Get guidance for value assignment based on persona category. (v16.12.0) Explains research basis for why cognitive, physical, sensory, and emotional disability categories require different value handling approaches.", {
|
|
2021
|
+
category: z.enum(["cognitive", "physical", "sensory", "emotional", "general"]).describe("Persona category to get guidance for"),
|
|
2022
|
+
}, async ({ category }) => {
|
|
2023
|
+
const { CATEGORY_VALUE_PRESETS, COGNITIVE_SUBTYPES } = await import("./persona-questionnaire.js");
|
|
2024
|
+
const preset = CATEGORY_VALUE_PRESETS.find(p => p.category === category);
|
|
2025
|
+
if (!preset) {
|
|
2026
|
+
return {
|
|
2027
|
+
content: [
|
|
2028
|
+
{
|
|
2029
|
+
type: "text",
|
|
2030
|
+
text: JSON.stringify({
|
|
2031
|
+
error: `Unknown category: ${category}`,
|
|
2032
|
+
availableCategories: ["cognitive", "physical", "sensory", "emotional", "general"],
|
|
2033
|
+
}, null, 2),
|
|
2034
|
+
},
|
|
2035
|
+
],
|
|
2036
|
+
};
|
|
2037
|
+
}
|
|
2038
|
+
return {
|
|
2039
|
+
content: [
|
|
2040
|
+
{
|
|
2041
|
+
type: "text",
|
|
2042
|
+
text: JSON.stringify({
|
|
2043
|
+
category: preset.category,
|
|
2044
|
+
description: preset.description,
|
|
2045
|
+
valueStrategy: preset.valueStrategy,
|
|
2046
|
+
guidance: preset.guidance,
|
|
2047
|
+
defaultValues: preset.defaultValues,
|
|
2048
|
+
researchBasis: preset.researchBasis,
|
|
2049
|
+
...(category === "cognitive" && {
|
|
2050
|
+
subtypes: Object.entries(COGNITIVE_SUBTYPES).map(([key, subtype]) => ({
|
|
2051
|
+
name: key,
|
|
2052
|
+
values: subtype.values,
|
|
2053
|
+
researchBasis: subtype.researchBasis,
|
|
2054
|
+
})),
|
|
2055
|
+
}),
|
|
2056
|
+
}, null, 2),
|
|
2057
|
+
},
|
|
2058
|
+
],
|
|
2059
|
+
};
|
|
2060
|
+
});
|
|
1650
2061
|
// =========================================================================
|
|
1651
2062
|
// Performance Tools (v6.4.0+)
|
|
1652
2063
|
// =========================================================================
|
|
@@ -1656,6 +2067,8 @@ Begin the simulation now. Narrate your thoughts as this persona.
|
|
|
1656
2067
|
runs: z.number().optional().default(3).describe("Number of runs to average"),
|
|
1657
2068
|
}, async ({ url, name, runs }) => {
|
|
1658
2069
|
const result = await capturePerformanceBaseline(url, { name, runs });
|
|
2070
|
+
// v16.11.0: Return all available metrics, not just core 4
|
|
2071
|
+
const m = result.metrics;
|
|
1659
2072
|
return {
|
|
1660
2073
|
content: [
|
|
1661
2074
|
{
|
|
@@ -1663,19 +2076,47 @@ Begin the simulation now. Narrate your thoughts as this persona.
|
|
|
1663
2076
|
text: JSON.stringify({
|
|
1664
2077
|
name: result.name,
|
|
1665
2078
|
url: result.url,
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
2079
|
+
// Core Web Vitals
|
|
2080
|
+
coreWebVitals: {
|
|
2081
|
+
lcp: m.lcp,
|
|
2082
|
+
lcpRating: m.lcpRating,
|
|
2083
|
+
fid: m.fid,
|
|
2084
|
+
fidRating: m.fidRating,
|
|
2085
|
+
cls: m.cls,
|
|
2086
|
+
clsRating: m.clsRating,
|
|
2087
|
+
},
|
|
2088
|
+
// Additional timing metrics
|
|
2089
|
+
timingMetrics: {
|
|
2090
|
+
fcp: m.fcp,
|
|
2091
|
+
fcpRating: m.fcpRating,
|
|
2092
|
+
ttfb: m.ttfb,
|
|
2093
|
+
ttfbRating: m.ttfbRating,
|
|
2094
|
+
tti: m.tti,
|
|
2095
|
+
tbt: m.tbt,
|
|
2096
|
+
domContentLoaded: m.domContentLoaded,
|
|
2097
|
+
load: m.load,
|
|
2098
|
+
},
|
|
2099
|
+
// Resource metrics
|
|
2100
|
+
resourceMetrics: {
|
|
2101
|
+
resourceCount: m.resourceCount,
|
|
2102
|
+
transferSize: m.transferSize,
|
|
2103
|
+
},
|
|
2104
|
+
// Flat copy for backward compatibility
|
|
2105
|
+
metrics: {
|
|
2106
|
+
lcp: m.lcp,
|
|
2107
|
+
fcp: m.fcp,
|
|
2108
|
+
ttfb: m.ttfb,
|
|
2109
|
+
cls: m.cls,
|
|
2110
|
+
},
|
|
1670
2111
|
}, null, 2),
|
|
1671
2112
|
},
|
|
1672
2113
|
],
|
|
1673
2114
|
};
|
|
1674
2115
|
});
|
|
1675
|
-
server.tool("perf_regression", "Detect performance regression against baseline with configurable sensitivity. Uses dual thresholds: both percentage AND absolute change must be exceeded. Profiles: strict (
|
|
2116
|
+
server.tool("perf_regression", "Detect performance regression against baseline with configurable sensitivity. Uses dual thresholds: both percentage AND absolute change must be exceeded. Profiles: strict (perf envs, FCP 10%/50ms), normal (default, FCP 20%/100ms), ci (automated pipelines, FCP 25%/150ms), lenient (dev, FCP 30%/200ms).", {
|
|
1676
2117
|
url: z.string().url().describe("URL to test"),
|
|
1677
2118
|
baselineName: z.string().describe("Name of baseline to compare against"),
|
|
1678
|
-
sensitivity: z.enum(["strict", "normal", "lenient"]).optional().default("normal").describe("Sensitivity profile: strict (
|
|
2119
|
+
sensitivity: z.enum(["strict", "normal", "ci", "lenient"]).optional().default("normal").describe("Sensitivity profile: strict (perf testing), normal (local dev), ci (automated pipelines), lenient (development)"),
|
|
1679
2120
|
thresholdLcp: z.number().optional().describe("Override LCP threshold percentage"),
|
|
1680
2121
|
}, async ({ url, baselineName, sensitivity, thresholdLcp }) => {
|
|
1681
2122
|
const result = await detectPerformanceRegression(url, baselineName, {
|