cbrowser 16.5.0 β†’ 16.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -6,7 +6,7 @@
6
6
  [![Grade A+](https://img.shields.io/badge/Grade-A+-brightgreen.svg)](https://claude.ai/public/artifacts/0cee560d-60b8-44d6-8eec-e674fbfac9c4)
7
7
  [![Tests](https://github.com/alexandriashai/cbrowser/actions/workflows/test.yml/badge.svg)](https://github.com/alexandriashai/cbrowser/actions/workflows/test.yml)
8
8
  [![License: BSL-1.1](https://img.shields.io/badge/License-BSL--1.1-blue.svg)](LICENSE)
9
- [![MCP Ready](https://img.shields.io/badge/MCP-45%20Tools-blue)](https://modelcontextprotocol.io)
9
+ [![MCP Ready](https://img.shields.io/badge/MCP-48%20Tools-blue)](https://modelcontextprotocol.io)
10
10
  [![TypeScript](https://img.shields.io/badge/TypeScript-5.3-blue.svg)](https://www.typescriptlang.org/)
11
11
  [![Node](https://img.shields.io/badge/Node-%3E%3D18-green.svg)](https://nodejs.org/)
12
12
 
@@ -21,11 +21,11 @@
21
21
  | Capability | Status | Why It Matters |
22
22
  |------------|--------|----------------|
23
23
  | **Natural Language Tests** | ⭐ Best-in-class | Write tests in plain English. 10-step E2E flows run 100% stable. |
24
- | **Cognitive User Simulation** | πŸ”¬ Novel | 12 research-backed traits model real human behaviorβ€”not just clicks. |
24
+ | **Cognitive User Simulation** | πŸ”¬ Novel | 25 research-backed traits model real human behaviorβ€”not just clicks. |
25
25
  | **Empathy Accessibility Audits** | πŸ”¬ Novel | Simulate users with tremors, low vision, ADHD. No competitor offers this. |
26
26
  | **Self-Healing Selectors** | βœ… Production-ready | ARIA-first with 0.8+ confidence gating. Handles DOM changes automatically. |
27
27
  | **Constitutional AI Safety** | πŸ”¬ Novel | Risk-classified actions prevent autonomous agents from doing damage. |
28
- | **45 MCP Tools** | βœ… Production-ready | Full Claude integrationβ€”local and remote servers. |
28
+ | **48 MCP Tools** | βœ… Production-ready | Full Claude integrationβ€”local and remote servers. |
29
29
 
30
30
  ---
31
31
 
@@ -124,6 +124,26 @@ Friction points:
124
124
  2. Form validation error not visible (step 6)
125
125
  ```
126
126
 
127
+ ### Custom Persona Builder (v16.6.0)
128
+
129
+ Create research-backed custom personas via interactive questionnaire:
130
+
131
+ ```bash
132
+ # Interactive questionnaire (8 core traits)
133
+ npx cbrowser persona-questionnaire start
134
+
135
+ # Comprehensive questionnaire (all 25 traits)
136
+ npx cbrowser persona-questionnaire start --comprehensive --name "my-tester"
137
+
138
+ # Look up trait behaviors
139
+ npx cbrowser persona-questionnaire lookup --trait patience --value 0.25
140
+
141
+ # List all available traits
142
+ npx cbrowser persona-questionnaire list-traits
143
+ ```
144
+
145
+ Each trait maps to research-backed behavioral descriptions with 5 levels (0, 0.25, 0.5, 0.75, 1.0).
146
+
127
147
  ---
128
148
 
129
149
  ## Natural Language Testing
@@ -251,7 +271,7 @@ Deploy your own: see [Remote MCP Server Guide](docs/REMOTE-MCP-SERVER.md)
251
271
  }
252
272
  ```
253
273
 
254
- ### 45 MCP Tools
274
+ ### 48 MCP Tools
255
275
 
256
276
  | Category | Tools |
257
277
  |----------|-------|
@@ -260,6 +280,7 @@ Deploy your own: see [Remote MCP Server Guide](docs/REMOTE-MCP-SERVER.md)
260
280
  | **Testing** | `test_suite`, `repair_tests`, `flaky_check` |
261
281
  | **Visual** | `visual_baseline`, `visual_compare`, `responsive_test`, `cross_browser_test`, `ab_compare` |
262
282
  | **Cognitive** | `cognitive_journey_init`, `cognitive_journey_update_state`, `compare_personas` |
283
+ | **Persona** | `persona_questionnaire_get`, `persona_questionnaire_build`, `persona_trait_lookup` |
263
284
  | **Analysis** | `hunt_bugs`, `chaos_test`, `agent_ready_audit`, `competitive_benchmark`, `empathy_audit` |
264
285
  | **Stealth** | `stealth_enable`, `stealth_disable`, `stealth_status`, `stealth_check`, `stealth_diagnose` |
265
286
 
package/dist/cli.js CHANGED
@@ -35,6 +35,24 @@ import { printEnterpriseStatus } from "./stealth/index.js";
35
35
  import { runCognitiveJourney, getAnthropicApiKey, setAnthropicApiKey, removeAnthropicApiKey, isApiKeyConfigured, } from "./cognitive/index.js";
36
36
  // Version from package.json - single source of truth
37
37
  import { VERSION } from "./version.js";
38
+ // Node readline for interactive input
39
+ import * as readline from "readline";
40
+ /**
41
+ * Helper function for interactive readline input.
42
+ */
43
+ function readlineQuestion(prompt) {
44
+ const rl = readline.createInterface({
45
+ input: process.stdin,
46
+ output: process.stdout,
47
+ terminal: process.stdin.isTTY || false,
48
+ });
49
+ return new Promise((resolve) => {
50
+ rl.question(prompt, (answer) => {
51
+ rl.close();
52
+ resolve(answer);
53
+ });
54
+ });
55
+ }
38
56
  function showHelp() {
39
57
  // Pad version string to maintain banner alignment
40
58
  const versionStr = `CBrowser CLI v${VERSION}`;
@@ -4612,6 +4630,157 @@ Documentation: https://github.com/alexandriashai/cbrowser/wiki
4612
4630
  }
4613
4631
  break;
4614
4632
  }
4633
+ // =========================================================================
4634
+ // Persona Questionnaire (v16.5.0) - Research-based custom persona builder
4635
+ // =========================================================================
4636
+ case "persona-questionnaire": {
4637
+ const subcommand = args[0];
4638
+ if (!subcommand || subcommand === "help") {
4639
+ console.log(`
4640
+ CBrowser Persona Questionnaire (v16.5.0)
4641
+ ========================================
4642
+
4643
+ Build custom personas using a research-based questionnaire that maps
4644
+ behavioral answers to cognitive traits.
4645
+
4646
+ Commands:
4647
+ persona-questionnaire start Start interactive questionnaire
4648
+ persona-questionnaire list-traits List all available traits with descriptions
4649
+ persona-questionnaire lookup Look up behaviors for a specific trait value
4650
+
4651
+ Options for 'start':
4652
+ --comprehensive Include all 25 traits (default: 8 core traits)
4653
+ --name <name> Name for the persona (prompted if not provided)
4654
+ --output <file> Save questionnaire answers to JSON file
4655
+
4656
+ Options for 'lookup':
4657
+ --trait <name> Trait name (e.g., patience, riskTolerance)
4658
+ --value <0-1> Trait value to look up
4659
+
4660
+ Examples:
4661
+ cbrowser persona-questionnaire start
4662
+ cbrowser persona-questionnaire start --comprehensive --name "my-tester"
4663
+ cbrowser persona-questionnaire list-traits
4664
+ cbrowser persona-questionnaire lookup --trait patience --value 0.25
4665
+ `);
4666
+ process.exit(0);
4667
+ }
4668
+ const { generatePersonaQuestionnaire, buildTraitsFromAnswers, getTraitReference, TRAIT_REFERENCE_MATRIX } = await import("./persona-questionnaire.js");
4669
+ const { createCognitivePersona, saveCustomPersona } = await import("./personas.js");
4670
+ switch (subcommand) {
4671
+ case "start": {
4672
+ const comprehensive = options.comprehensive === true;
4673
+ const questions = generatePersonaQuestionnaire({ comprehensive });
4674
+ console.log(`\n🧠 CBrowser Persona Questionnaire`);
4675
+ console.log(`━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`);
4676
+ console.log(`This questionnaire will help you create a research-backed persona.`);
4677
+ console.log(`Answer each question to define cognitive traits.\n`);
4678
+ // Get persona name
4679
+ let personaName = options.name;
4680
+ if (!personaName) {
4681
+ console.log(`Enter a name for this persona:`);
4682
+ personaName = await readlineQuestion("> ") || "custom-persona";
4683
+ }
4684
+ console.log(`\nCreating persona: ${personaName}\n`);
4685
+ // Collect answers
4686
+ const answers = {};
4687
+ for (let i = 0; i < questions.length; i++) {
4688
+ const q = questions[i];
4689
+ console.log(`\n[${i + 1}/${questions.length}] ${q.question}\n`);
4690
+ q.options.forEach((opt, idx) => {
4691
+ console.log(` ${idx + 1}. ${opt.label}`);
4692
+ console.log(` ${opt.description}`);
4693
+ });
4694
+ console.log(`\nEnter 1-${q.options.length} (or press Enter for default):`);
4695
+ const answer = await readlineQuestion("> ");
4696
+ if (answer && answer.trim()) {
4697
+ const idx = parseInt(answer.trim()) - 1;
4698
+ if (idx >= 0 && idx < q.options.length) {
4699
+ answers[q.trait] = q.options[idx].value;
4700
+ console.log(` βœ“ ${q.options[idx].label}`);
4701
+ }
4702
+ }
4703
+ else {
4704
+ console.log(` β†’ Using default (moderate)`);
4705
+ }
4706
+ }
4707
+ // Build persona
4708
+ console.log(`\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`);
4709
+ console.log(`Building persona...`);
4710
+ const traits = buildTraitsFromAnswers(answers);
4711
+ const persona = createCognitivePersona(personaName, `Custom persona created via questionnaire`, traits, {});
4712
+ const savedPath = saveCustomPersona(persona);
4713
+ console.log(`\nβœ“ Persona saved: ${savedPath}`);
4714
+ console.log(`\nπŸ“Š Trait Summary:`);
4715
+ // Show non-default traits
4716
+ for (const [trait, value] of Object.entries(traits)) {
4717
+ if (value !== 0.5) {
4718
+ const ref = TRAIT_REFERENCE_MATRIX.find(t => t.name === trait);
4719
+ if (ref) {
4720
+ const level = ref.levels.reduce((prev, curr) => Math.abs(curr.value - value) < Math.abs(prev.value - value) ? curr : prev);
4721
+ console.log(` ${trait}: ${value.toFixed(2)} (${level.label})`);
4722
+ }
4723
+ }
4724
+ }
4725
+ console.log(`\nπŸ’‘ Use with: cbrowser cognitive-journey --persona "${personaName}" --start <url> --goal "<goal>"`);
4726
+ // Save answers if requested
4727
+ if (options.output) {
4728
+ const fs = await import("fs");
4729
+ fs.writeFileSync(options.output, JSON.stringify({ name: personaName, answers, traits }, null, 2));
4730
+ console.log(`\nπŸ“ Answers saved: ${options.output}`);
4731
+ }
4732
+ break;
4733
+ }
4734
+ case "list-traits": {
4735
+ console.log(`\n🧠 CBrowser Cognitive Traits Reference`);
4736
+ console.log(`━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`);
4737
+ console.log(`${TRAIT_REFERENCE_MATRIX.length} research-backed traits available:\n`);
4738
+ for (const trait of TRAIT_REFERENCE_MATRIX) {
4739
+ console.log(`πŸ“ ${trait.name}`);
4740
+ console.log(` ${trait.description}`);
4741
+ console.log(` Research: ${trait.researchBasis}`);
4742
+ console.log(` Scale: ${trait.levels[0].label} (0) β†’ ${trait.levels[4].label} (1)`);
4743
+ console.log();
4744
+ }
4745
+ break;
4746
+ }
4747
+ case "lookup": {
4748
+ const traitName = options.trait;
4749
+ const traitValue = parseFloat(options.value);
4750
+ if (!traitName) {
4751
+ console.error("Error: --trait <name> required");
4752
+ console.error("Use 'persona-questionnaire list-traits' to see available traits");
4753
+ process.exit(1);
4754
+ }
4755
+ if (isNaN(traitValue) || traitValue < 0 || traitValue > 1) {
4756
+ console.error("Error: --value must be a number between 0 and 1");
4757
+ process.exit(1);
4758
+ }
4759
+ const ref = getTraitReference(traitName);
4760
+ if (!ref) {
4761
+ console.error(`Error: Unknown trait "${traitName}"`);
4762
+ console.error("Use 'persona-questionnaire list-traits' to see available traits");
4763
+ process.exit(1);
4764
+ }
4765
+ const level = ref.levels.reduce((prev, curr) => Math.abs(curr.value - traitValue) < Math.abs(prev.value - traitValue) ? curr : prev);
4766
+ console.log(`\nπŸ“ ${ref.name} = ${traitValue}`);
4767
+ console.log(`━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━`);
4768
+ console.log(`Description: ${ref.description}`);
4769
+ console.log(`Research: ${ref.researchBasis}`);
4770
+ console.log(`\nLevel: ${level.label} (${level.value})`);
4771
+ console.log(`\nBehaviors:`);
4772
+ for (const behavior of level.behaviors) {
4773
+ console.log(` β€’ ${behavior}`);
4774
+ }
4775
+ break;
4776
+ }
4777
+ default:
4778
+ console.error(`Unknown subcommand: ${subcommand}`);
4779
+ console.error("Use 'persona-questionnaire help' for usage");
4780
+ process.exit(1);
4781
+ }
4782
+ break;
4783
+ }
4615
4784
  default:
4616
4785
  console.error(`Unknown command: ${command}`);
4617
4786
  console.error("Run 'cbrowser help' for usage");