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.
Files changed (39) hide show
  1. package/README.md +32 -0
  2. package/dist/analysis/chaos-testing.d.ts.map +1 -1
  3. package/dist/analysis/chaos-testing.js +8 -1
  4. package/dist/analysis/chaos-testing.js.map +1 -1
  5. package/dist/browser.d.ts +8 -0
  6. package/dist/browser.d.ts.map +1 -1
  7. package/dist/browser.js +144 -1
  8. package/dist/browser.js.map +1 -1
  9. package/dist/cli.js +3 -2
  10. package/dist/cli.js.map +1 -1
  11. package/dist/mcp-server-remote.d.ts.map +1 -1
  12. package/dist/mcp-server-remote.js +468 -33
  13. package/dist/mcp-server-remote.js.map +1 -1
  14. package/dist/mcp-server.d.ts.map +1 -1
  15. package/dist/mcp-server.js +513 -33
  16. package/dist/mcp-server.js.map +1 -1
  17. package/dist/performance/metrics.d.ts +2 -2
  18. package/dist/performance/metrics.d.ts.map +1 -1
  19. package/dist/performance/metrics.js +37 -1
  20. package/dist/performance/metrics.js.map +1 -1
  21. package/dist/persona-questionnaire.d.ts +103 -1
  22. package/dist/persona-questionnaire.d.ts.map +1 -1
  23. package/dist/persona-questionnaire.js +396 -35
  24. package/dist/persona-questionnaire.js.map +1 -1
  25. package/dist/personas.d.ts.map +1 -1
  26. package/dist/personas.js +4 -0
  27. package/dist/personas.js.map +1 -1
  28. package/dist/types.d.ts +2 -2
  29. package/dist/types.d.ts.map +1 -1
  30. package/dist/values/persona-values.d.ts +5 -0
  31. package/dist/values/persona-values.d.ts.map +1 -1
  32. package/dist/values/persona-values.js +79 -38
  33. package/dist/values/persona-values.js.map +1 -1
  34. package/dist/visual/cross-browser.d.ts.map +1 -1
  35. package/dist/visual/cross-browser.js +10 -1
  36. package/dist/visual/cross-browser.js.map +1 -1
  37. package/docs/personas/Persona-Index.md +126 -0
  38. package/docs/research/Values-Research.md +375 -0
  39. 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;AAisFH;;GAEG;AACH,wBAAsB,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC,CA8L1D"}
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
- const result = await runChaosTest(b, url, { networkLatency, offline, blockUrls });
996
- return {
997
- content: [
998
- {
999
- type: "text",
1000
- text: JSON.stringify({
1001
- passed: result.passed,
1002
- errors: result.errors,
1003
- duration: result.duration,
1004
- }, null, 2),
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
- }).optional().describe("Override specific cognitive traits"),
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
- // Merge custom traits with defaults
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
- const names = listPersonas();
1508
- const personas = names.map(name => {
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({ personas, count: personas.length }, null, 2),
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
- }, async ({ comprehensive, traits }) => {
1539
- const { generatePersonaQuestionnaire, formatForAskUserQuestion } = await import("./persona-questionnaire.js");
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
- lcp: result.metrics.lcp,
1667
- fcp: result.metrics.fcp,
1668
- ttfb: result.metrics.ttfb,
1669
- cls: result.metrics.cls,
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 (CI/CD, FCP 10%/50ms), normal (default, FCP 20%/100ms), lenient (dev, FCP 30%/200ms). Sub-50ms FCP variations ignored by default.", {
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 (CI/CD), normal (default), lenient (development)"),
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, {