cbrowser 16.9.4 → 16.13.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 +468 -33
- package/dist/mcp-server-remote.js.map +1 -1
- package/dist/mcp-server.d.ts.map +1 -1
- package/dist/mcp-server.js +513 -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 +103 -1
- package/dist/persona-questionnaire.d.ts.map +1 -1
- package/dist/persona-questionnaire.js +396 -35
- package/dist/persona-questionnaire.js.map +1 -1
- package/dist/personas.d.ts.map +1 -1
- package/dist/personas.js +4 -0
- package/dist/personas.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 +375 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-server-remote.d.ts","sourceRoot":"","sources":["../src/mcp-server-remote.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;GAWG;
|
|
1
|
+
{"version":3,"file":"mcp-server-remote.d.ts","sourceRoot":"","sources":["../src/mcp-server-remote.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;GAWG;AAqqGH;;GAEG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC,CA8L1D"}
|
|
@@ -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];
|
|
1750
|
+
return {
|
|
1751
|
+
content: [
|
|
1752
|
+
{
|
|
1753
|
+
type: "text",
|
|
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
|
+
}));
|
|
1522
1859
|
return {
|
|
1523
1860
|
content: [
|
|
1524
1861
|
{
|
|
1525
1862
|
type: "text",
|
|
1526
|
-
text: JSON.stringify({
|
|
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,23 +1890,35 @@ 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");
|
|
1916
|
+
// Detect or use provided category
|
|
1917
|
+
const detectedCategory = category || detectPersonaCategory(name, description);
|
|
1918
|
+
// Build category-appropriate values with optional overrides
|
|
1919
|
+
const categoryResult = buildValuesFromCategory(detectedCategory, valueOverrides);
|
|
1920
|
+
// Validate values match category guidelines
|
|
1921
|
+
const warnings = validateCategoryValues(detectedCategory, categoryResult.values);
|
|
1567
1922
|
// Build traits from answers with research-based correlations
|
|
1568
1923
|
const traits = buildTraitsFromAnswers(answers);
|
|
1569
1924
|
// Create the persona
|
|
@@ -1597,6 +1952,15 @@ Begin the simulation now. Narrate your thoughts as this persona.
|
|
|
1597
1952
|
},
|
|
1598
1953
|
cognitiveTraits: traits,
|
|
1599
1954
|
traitSummary,
|
|
1955
|
+
// v16.12.0: Category-aware values
|
|
1956
|
+
category: {
|
|
1957
|
+
detected: detectedCategory,
|
|
1958
|
+
strategy: categoryResult.valueStrategy,
|
|
1959
|
+
guidance: categoryResult.guidance,
|
|
1960
|
+
},
|
|
1961
|
+
values: categoryResult.values,
|
|
1962
|
+
researchBasis: categoryResult.researchBasis,
|
|
1963
|
+
...(warnings.length > 0 && { warnings }),
|
|
1600
1964
|
savedPath,
|
|
1601
1965
|
usage: `Use persona "${name}" with cognitive-journey or other commands`,
|
|
1602
1966
|
}, null, 2),
|
|
@@ -1647,6 +2011,47 @@ Begin the simulation now. Narrate your thoughts as this persona.
|
|
|
1647
2011
|
],
|
|
1648
2012
|
};
|
|
1649
2013
|
});
|
|
2014
|
+
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.", {
|
|
2015
|
+
category: z.enum(["cognitive", "physical", "sensory", "emotional", "general"]).describe("Persona category to get guidance for"),
|
|
2016
|
+
}, async ({ category }) => {
|
|
2017
|
+
const { CATEGORY_VALUE_PRESETS, COGNITIVE_SUBTYPES } = await import("./persona-questionnaire.js");
|
|
2018
|
+
const preset = CATEGORY_VALUE_PRESETS.find(p => p.category === category);
|
|
2019
|
+
if (!preset) {
|
|
2020
|
+
return {
|
|
2021
|
+
content: [
|
|
2022
|
+
{
|
|
2023
|
+
type: "text",
|
|
2024
|
+
text: JSON.stringify({
|
|
2025
|
+
error: `Unknown category: ${category}`,
|
|
2026
|
+
availableCategories: ["cognitive", "physical", "sensory", "emotional", "general"],
|
|
2027
|
+
}, null, 2),
|
|
2028
|
+
},
|
|
2029
|
+
],
|
|
2030
|
+
};
|
|
2031
|
+
}
|
|
2032
|
+
return {
|
|
2033
|
+
content: [
|
|
2034
|
+
{
|
|
2035
|
+
type: "text",
|
|
2036
|
+
text: JSON.stringify({
|
|
2037
|
+
category: preset.category,
|
|
2038
|
+
description: preset.description,
|
|
2039
|
+
valueStrategy: preset.valueStrategy,
|
|
2040
|
+
guidance: preset.guidance,
|
|
2041
|
+
defaultValues: preset.defaultValues,
|
|
2042
|
+
researchBasis: preset.researchBasis,
|
|
2043
|
+
...(category === "cognitive" && {
|
|
2044
|
+
subtypes: Object.entries(COGNITIVE_SUBTYPES).map(([key, subtype]) => ({
|
|
2045
|
+
name: key,
|
|
2046
|
+
values: subtype.values,
|
|
2047
|
+
researchBasis: subtype.researchBasis,
|
|
2048
|
+
})),
|
|
2049
|
+
}),
|
|
2050
|
+
}, null, 2),
|
|
2051
|
+
},
|
|
2052
|
+
],
|
|
2053
|
+
};
|
|
2054
|
+
});
|
|
1650
2055
|
// =========================================================================
|
|
1651
2056
|
// Performance Tools (v6.4.0+)
|
|
1652
2057
|
// =========================================================================
|
|
@@ -1656,6 +2061,8 @@ Begin the simulation now. Narrate your thoughts as this persona.
|
|
|
1656
2061
|
runs: z.number().optional().default(3).describe("Number of runs to average"),
|
|
1657
2062
|
}, async ({ url, name, runs }) => {
|
|
1658
2063
|
const result = await capturePerformanceBaseline(url, { name, runs });
|
|
2064
|
+
// v16.11.0: Return all available metrics, not just core 4
|
|
2065
|
+
const m = result.metrics;
|
|
1659
2066
|
return {
|
|
1660
2067
|
content: [
|
|
1661
2068
|
{
|
|
@@ -1663,19 +2070,47 @@ Begin the simulation now. Narrate your thoughts as this persona.
|
|
|
1663
2070
|
text: JSON.stringify({
|
|
1664
2071
|
name: result.name,
|
|
1665
2072
|
url: result.url,
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
2073
|
+
// Core Web Vitals
|
|
2074
|
+
coreWebVitals: {
|
|
2075
|
+
lcp: m.lcp,
|
|
2076
|
+
lcpRating: m.lcpRating,
|
|
2077
|
+
fid: m.fid,
|
|
2078
|
+
fidRating: m.fidRating,
|
|
2079
|
+
cls: m.cls,
|
|
2080
|
+
clsRating: m.clsRating,
|
|
2081
|
+
},
|
|
2082
|
+
// Additional timing metrics
|
|
2083
|
+
timingMetrics: {
|
|
2084
|
+
fcp: m.fcp,
|
|
2085
|
+
fcpRating: m.fcpRating,
|
|
2086
|
+
ttfb: m.ttfb,
|
|
2087
|
+
ttfbRating: m.ttfbRating,
|
|
2088
|
+
tti: m.tti,
|
|
2089
|
+
tbt: m.tbt,
|
|
2090
|
+
domContentLoaded: m.domContentLoaded,
|
|
2091
|
+
load: m.load,
|
|
2092
|
+
},
|
|
2093
|
+
// Resource metrics
|
|
2094
|
+
resourceMetrics: {
|
|
2095
|
+
resourceCount: m.resourceCount,
|
|
2096
|
+
transferSize: m.transferSize,
|
|
2097
|
+
},
|
|
2098
|
+
// Flat copy for backward compatibility
|
|
2099
|
+
metrics: {
|
|
2100
|
+
lcp: m.lcp,
|
|
2101
|
+
fcp: m.fcp,
|
|
2102
|
+
ttfb: m.ttfb,
|
|
2103
|
+
cls: m.cls,
|
|
2104
|
+
},
|
|
1670
2105
|
}, null, 2),
|
|
1671
2106
|
},
|
|
1672
2107
|
],
|
|
1673
2108
|
};
|
|
1674
2109
|
});
|
|
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 (
|
|
2110
|
+
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
2111
|
url: z.string().url().describe("URL to test"),
|
|
1677
2112
|
baselineName: z.string().describe("Name of baseline to compare against"),
|
|
1678
|
-
sensitivity: z.enum(["strict", "normal", "lenient"]).optional().default("normal").describe("Sensitivity profile: strict (
|
|
2113
|
+
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
2114
|
thresholdLcp: z.number().optional().describe("Override LCP threshold percentage"),
|
|
1680
2115
|
}, async ({ url, baselineName, sensitivity, thresholdLcp }) => {
|
|
1681
2116
|
const result = await detectPerformanceRegression(url, baselineName, {
|