quorum-ux 0.1.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 (67) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +196 -0
  3. package/dist/commands/init.d.ts +7 -0
  4. package/dist/commands/init.d.ts.map +1 -0
  5. package/dist/commands/init.js +223 -0
  6. package/dist/commands/init.js.map +1 -0
  7. package/dist/config/global.d.ts +22 -0
  8. package/dist/config/global.d.ts.map +1 -0
  9. package/dist/config/global.js +87 -0
  10. package/dist/config/global.js.map +1 -0
  11. package/dist/index.d.ts +18 -0
  12. package/dist/index.d.ts.map +1 -0
  13. package/dist/index.js +440 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/models/openrouter.d.ts +47 -0
  16. package/dist/models/openrouter.d.ts.map +1 -0
  17. package/dist/models/openrouter.js +89 -0
  18. package/dist/models/openrouter.js.map +1 -0
  19. package/dist/personas/archetypes.d.ts +9 -0
  20. package/dist/personas/archetypes.d.ts.map +1 -0
  21. package/dist/personas/archetypes.js +90 -0
  22. package/dist/personas/archetypes.js.map +1 -0
  23. package/dist/personas/index.d.ts +16 -0
  24. package/dist/personas/index.d.ts.map +1 -0
  25. package/dist/personas/index.js +38 -0
  26. package/dist/personas/index.js.map +1 -0
  27. package/dist/pipeline/analyze-video.d.ts +10 -0
  28. package/dist/pipeline/analyze-video.d.ts.map +1 -0
  29. package/dist/pipeline/analyze-video.js +204 -0
  30. package/dist/pipeline/analyze-video.js.map +1 -0
  31. package/dist/pipeline/analyze.d.ts +10 -0
  32. package/dist/pipeline/analyze.d.ts.map +1 -0
  33. package/dist/pipeline/analyze.js +153 -0
  34. package/dist/pipeline/analyze.js.map +1 -0
  35. package/dist/pipeline/extract-frames.d.ts +9 -0
  36. package/dist/pipeline/extract-frames.d.ts.map +1 -0
  37. package/dist/pipeline/extract-frames.js +129 -0
  38. package/dist/pipeline/extract-frames.js.map +1 -0
  39. package/dist/pipeline/report.d.ts +11 -0
  40. package/dist/pipeline/report.d.ts.map +1 -0
  41. package/dist/pipeline/report.js +286 -0
  42. package/dist/pipeline/report.js.map +1 -0
  43. package/dist/pipeline/synthesize.d.ts +10 -0
  44. package/dist/pipeline/synthesize.d.ts.map +1 -0
  45. package/dist/pipeline/synthesize.js +178 -0
  46. package/dist/pipeline/synthesize.js.map +1 -0
  47. package/dist/types.d.ts +225 -0
  48. package/dist/types.d.ts.map +1 -0
  49. package/dist/types.js +7 -0
  50. package/dist/types.js.map +1 -0
  51. package/dist/utils/costs.d.ts +52 -0
  52. package/dist/utils/costs.d.ts.map +1 -0
  53. package/dist/utils/costs.js +165 -0
  54. package/dist/utils/costs.js.map +1 -0
  55. package/dist/utils/files.d.ts +33 -0
  56. package/dist/utils/files.d.ts.map +1 -0
  57. package/dist/utils/files.js +88 -0
  58. package/dist/utils/files.js.map +1 -0
  59. package/dist/utils/logger.d.ts +15 -0
  60. package/dist/utils/logger.d.ts.map +1 -0
  61. package/dist/utils/logger.js +43 -0
  62. package/dist/utils/logger.js.map +1 -0
  63. package/dist/utils/prompt.d.ts +24 -0
  64. package/dist/utils/prompt.d.ts.map +1 -0
  65. package/dist/utils/prompt.js +95 -0
  66. package/dist/utils/prompt.js.map +1 -0
  67. package/package.json +65 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Jason Shearer
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,196 @@
1
+ # QuorumUX
2
+
3
+ **Multi-model consensus UX analysis from E2E test artifacts.**
4
+
5
+ QuorumUX sends your Playwright screenshots and video recordings to multiple AI vision models, then synthesizes their findings into a single prioritized report with consensus-weighted severity. Issues flagged by 2+ models are high confidence. Video analysis catches temporal friction (hesitation, confusion, loading delays) that screenshots miss.
6
+
7
+ ## How It Works
8
+
9
+ <div align="center">
10
+
11
+ ![QuorumUX Pipeline Diagram](docs/pipeline.svg)
12
+
13
+ </div>
14
+
15
+ ## What Makes This Different
16
+
17
+ Most visual testing tools compare pixels. QuorumUX asks AI models to think like UX researchers.
18
+
19
+ - **Multi-model consensus** — 3 models analyze independently, a 4th synthesizes. Issues flagged by 2+ models are high confidence. Single-model findings need human review. Disagreements are surfaced explicitly.
20
+ - **Video temporal analysis** — Gemini watches your screen recordings and identifies hesitation (cursor pauses), confusion (backtracking), interaction patterns (rage clicks), and loading delays. This catches friction invisible to static screenshots.
21
+ - **Persona-aware context** — Feed your test runner's persona summaries (pass/fail/friction counts, known issues) into the analysis. Models evaluate against user intent, not just visual state.
22
+ - **Severity synthesis** — Opus weighs evidence from all sources (3 screenshot models + video + test results) and assigns P0/P1/P2 severity with effort estimates.
23
+ - **$3-5 per full run** — 10 personas × 3 models + video + synthesis costs pennies via OpenRouter.
24
+
25
+ ## Quickstart
26
+
27
+ ```bash
28
+ # Install
29
+ npm install quorum-ux
30
+
31
+ # Interactive setup — walks you through API key, personas, and model selection
32
+ npx quorumux init
33
+
34
+ # Preview what the pipeline will do and estimated cost
35
+ npx quorumux --dry-run
36
+
37
+ # Run the full pipeline
38
+ npx quorumux
39
+ ```
40
+
41
+ Or configure manually:
42
+
43
+ ```bash
44
+ cat > quorumux.config.ts << 'EOF'
45
+ import type { QuorumUXConfig } from 'quorum-ux';
46
+
47
+ const config: QuorumUXConfig = {
48
+ name: 'MyApp',
49
+ description: 'A project management tool for distributed teams',
50
+ domain: 'productivity',
51
+ appUrl: 'https://myapp.com',
52
+ userJourney: 'Signup → Create Project → Invite Team → Assign Tasks → Daily Standup',
53
+ artifactsDir: './test-artifacts',
54
+ models: {
55
+ screenshot: [
56
+ { id: 'anthropic/claude-sonnet-4.6', name: 'claude' },
57
+ { id: 'google/gemini-2.0-flash-001', name: 'gemini' },
58
+ { id: 'openai/gpt-4o-2024-11-20', name: 'gpt4o' },
59
+ ],
60
+ video: { id: 'google/gemini-2.0-flash-001', name: 'gemini' },
61
+ synthesis: { id: 'anthropic/claude-opus-4.5', name: 'opus' },
62
+ },
63
+ };
64
+
65
+ export default config;
66
+ EOF
67
+
68
+ OPENROUTER_API_KEY=sk-or-... npx quorumux
69
+ ```
70
+
71
+ ## Prerequisites
72
+
73
+ - **Node.js** >= 18
74
+ - **OpenRouter API key** — [openrouter.ai/keys](https://openrouter.ai/keys)
75
+ - **ffmpeg** — for video frame extraction (`brew install ffmpeg` / `apt install ffmpeg`)
76
+ - **ImageMagick** — for screenshot grids (`brew install imagemagick` / `apt install imagemagick`)
77
+ - **Test artifacts** — screenshots and/or video recordings from your E2E test runner (Playwright recommended)
78
+
79
+ ## Artifact Directory Structure
80
+
81
+ QuorumUX expects your test runner to produce artifacts in this structure:
82
+
83
+ ```
84
+ test-artifacts/
85
+ └── run-2026-02-22T09-00/ # Timestamped run directory
86
+ ├── videos/
87
+ │ └── P01-maria/ # One subdir per persona
88
+ │ └── abc123.webm # Playwright video recording
89
+ ├── screenshots/
90
+ │ └── P01-maria/
91
+ │ ├── P01-maria-step01-PASS-login.png
92
+ │ ├── P01-maria-step02-PASS-signup.png
93
+ │ └── P01-maria-step03-FRICTION-onboarding.png
94
+ ├── summaries/
95
+ │ └── P01-maria-summary.json # Test runner's structured results
96
+ └── executive-summary.md # Optional: test runner's summary
97
+ ```
98
+
99
+ Naming conventions are flexible — QuorumUX discovers personas from subdirectory names.
100
+
101
+ ## CLI Reference
102
+
103
+ ```
104
+ npx quorumux [command] [options]
105
+
106
+ Commands:
107
+ init Interactive project setup wizard
108
+ run [options] Run the analysis pipeline (default)
109
+
110
+ Options:
111
+ --config <path> Path to quorumux.config.ts (default: ./quorumux.config.ts)
112
+ --run-dir <path> Specific run directory (auto-detects latest run-*)
113
+ --start-stage <n> Start from stage 1, 2, 3, or 4 (default: 1)
114
+ --skip-video Skip Stage 2b video analysis
115
+ --dry-run Show what would run without making API calls
116
+ --verbose Verbose output
117
+ --help Show help
118
+
119
+ Environment:
120
+ OPENROUTER_API_KEY API key for OpenRouter (preferred).
121
+ Also reads from .env / .env.local or ~/.quorumux/config.json.
122
+ ```
123
+
124
+ ## Pipeline Stages
125
+
126
+ | Stage | Input | Output | Models Used |
127
+ |-------|-------|--------|-------------|
128
+ | **1: Extract** | videos/, screenshots/ | frames/, grids/ | None (ffmpeg + ImageMagick) |
129
+ | **2: Analyze Screenshots** | grids/, summaries/ | all-analyses-raw.json | All `config.models.screenshot` |
130
+ | **2b: Analyze Video** | videos/, summaries/ | all-video-analyses-raw.json | `config.models.video` |
131
+ | **3: Synthesize** | All Stage 2/2b output + summaries + exec summary | synthesis.json | `config.models.synthesis` |
132
+ | **4: Report** | synthesis.json | ux-analysis-report.md, github-issues.md | None (templating) |
133
+
134
+ Stages 2 and 2b run in parallel. You can start from any stage with `--start-stage`.
135
+
136
+ ## Persona Archetypes
137
+
138
+ QuorumUX includes 10 built-in persona archetypes for universal UX testing. Select them during `quorumux init` or reference them in your config:
139
+
140
+ | Archetype | Testing Focus | Device |
141
+ |-----------|--------------|--------|
142
+ | **Happy Path Hero** | Ideal journey, full completion | Desktop |
143
+ | **Speed Runner** | Skip/rush behavior, task efficiency | Desktop |
144
+ | **Cautious Explorer** | Reads everything, hesitates | Desktop |
145
+ | **Mobile-First User** | Touch interactions, small viewport | Mobile |
146
+ | **Accessibility User** | Screen reader, keyboard nav | Desktop |
147
+ | **Distracted Multitasker** | Tab switching, mid-flow pauses | Desktop |
148
+ | **Error-Prone Novice** | Wrong inputs, recovery paths | Desktop |
149
+ | **Power User** | Keyboard shortcuts, advanced features | Desktop |
150
+ | **Skeptical Evaluator** | Edge cases, competitor comparison | Desktop |
151
+ | **International User** | i18n, locale, long text | Desktop |
152
+
153
+ When persona IDs match an archetype, QuorumUX automatically injects behavioral context into the analysis prompts so models know what to look for.
154
+
155
+ ## Output: What You Get
156
+
157
+ ### ux-analysis-report.md
158
+
159
+ - **Overall assessment**: UX score (1-10), launch readiness, strengths, critical path
160
+ - **Consensus issues**: High-confidence findings from 2+ models, with video insight annotations
161
+ - **Video-only issues**: Temporal friction invisible to screenshots (hesitation, loading, confusion)
162
+ - **Model-unique issues**: Single-model findings that need human review
163
+ - **Disagreements**: Where models actively contradict each other
164
+
165
+ ### github-issues.md
166
+
167
+ Ready-to-paste `gh issue create` commands for every finding, with severity labels and structured descriptions.
168
+
169
+ ### synthesis.json
170
+
171
+ Raw structured data for programmatic consumption or custom reporting.
172
+
173
+ ## Integrating with Your Test Runner
174
+
175
+ QuorumUX is test-runner agnostic. It consumes artifacts, not test code. Any runner that produces screenshots and/or video works:
176
+
177
+ - **Playwright** (recommended): Use `recordVideo` on browser context + `page.screenshot()` at checkpoints
178
+ - **Cypress**: Use `cy.screenshot()` + video recording config
179
+ - **Puppeteer**: Use `page.screenshot()` + screen recording via Chrome DevTools Protocol
180
+
181
+ The optional `summaries/*.json` files give QuorumUX additional context (pass/fail counts, known issues) but aren't required. Without them, analysis is purely visual.
182
+
183
+ ## Cost
184
+
185
+ Typical cost for a 10-persona run via OpenRouter:
186
+
187
+ | Stage | Models | ~Cost |
188
+ |-------|--------|-------|
189
+ | Screenshots | 3 models × 10 personas | ~$1.50 |
190
+ | Video | Gemini × 10-12 videos | ~$0.50 |
191
+ | Synthesis | Opus × 1 call (~60K tokens) | ~$1.50 |
192
+ | **Total** | | **~$3.50** |
193
+
194
+ ## License
195
+
196
+ MIT
@@ -0,0 +1,7 @@
1
+ /**
2
+ * `quorumux init` — Interactive Project Setup Wizard
3
+ *
4
+ * Walks the user through configuring a new project and generates quorumux.config.ts.
5
+ */
6
+ export declare function runInit(): Promise<void>;
7
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAkEH,wBAAsB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAgE7C"}
@@ -0,0 +1,223 @@
1
+ /**
2
+ * `quorumux init` — Interactive Project Setup Wizard
3
+ *
4
+ * Walks the user through configuring a new project and generates quorumux.config.ts.
5
+ */
6
+ import * as fs from 'fs';
7
+ import * as path from 'path';
8
+ import { ask, select, confirm, closePrompt } from '../utils/prompt';
9
+ import { resolveApiKey, loadGlobalConfig, saveGlobalConfig } from '../config/global';
10
+ import { PERSONA_BUNDLES, getArchetypeSubset } from '../personas';
11
+ const DOMAINS = [
12
+ { label: 'Career Tech', value: 'career-tech' },
13
+ { label: 'Fintech', value: 'fintech' },
14
+ { label: 'Healthcare', value: 'healthcare' },
15
+ { label: 'E-commerce', value: 'e-commerce' },
16
+ { label: 'SaaS', value: 'saas' },
17
+ { label: 'Social', value: 'social' },
18
+ { label: 'Education', value: 'education' },
19
+ { label: 'Other', value: 'other' },
20
+ ];
21
+ const TESTING_DEPTHS = [
22
+ {
23
+ label: 'Fast (~$1)',
24
+ value: 'fast',
25
+ description: '1 screenshot model, no video, Gemini synthesis',
26
+ models: {
27
+ screenshot: [{ id: 'google/gemini-2.0-flash-001', name: 'gemini' }],
28
+ video: { id: 'google/gemini-2.0-flash-001', name: 'gemini' },
29
+ synthesis: { id: 'google/gemini-2.0-flash-001', name: 'gemini' },
30
+ },
31
+ },
32
+ {
33
+ label: 'Balanced (~$4)',
34
+ value: 'balanced',
35
+ description: '3 screenshot models, video, Opus synthesis (recommended)',
36
+ models: {
37
+ screenshot: [
38
+ { id: 'anthropic/claude-sonnet-4.6', name: 'claude' },
39
+ { id: 'google/gemini-2.0-flash-001', name: 'gemini' },
40
+ { id: 'openai/gpt-4o-2024-11-20', name: 'gpt4o' },
41
+ ],
42
+ video: { id: 'google/gemini-2.0-flash-001', name: 'gemini' },
43
+ synthesis: { id: 'anthropic/claude-opus-4.5', name: 'opus' },
44
+ },
45
+ },
46
+ {
47
+ label: 'Thorough (~$8)',
48
+ value: 'thorough',
49
+ description: '3 screenshot models (high token limits), video, Opus synthesis with extended analysis',
50
+ models: {
51
+ screenshot: [
52
+ { id: 'anthropic/claude-sonnet-4.6', name: 'claude', maxTokens: 5000 },
53
+ { id: 'google/gemini-2.0-flash-001', name: 'gemini', maxTokens: 5000 },
54
+ { id: 'openai/gpt-4o-2024-11-20', name: 'gpt4o', maxTokens: 5000 },
55
+ ],
56
+ video: { id: 'google/gemini-2.0-flash-001', name: 'gemini', maxTokens: 6000 },
57
+ synthesis: { id: 'anthropic/claude-opus-4.5', name: 'opus', maxTokens: 12000 },
58
+ },
59
+ },
60
+ ];
61
+ export async function runInit() {
62
+ console.log('\n QuorumUX — Project Setup\n');
63
+ try {
64
+ // Step 1: API Key
65
+ const apiKey = await resolveApiKeyStep();
66
+ // Step 2: Project Basics
67
+ const name = await ask('Project name');
68
+ const description = await ask('One-line description');
69
+ const domain = await select('What domain is your app in?', [...DOMAINS]);
70
+ const appUrl = await ask('App URL (e.g. https://myapp.com)');
71
+ // Step 3: User Journey
72
+ const userJourney = await ask('Describe the primary user flow to test');
73
+ // Step 4: Personas
74
+ const personaIds = await selectPersonas();
75
+ // Step 5: Testing Depth
76
+ const depth = await select('Testing depth?', TESTING_DEPTHS);
77
+ const models = TESTING_DEPTHS.find((d) => d.value === depth).models;
78
+ // Step 6: Artifacts Directory
79
+ const artifactsDir = await ask('Artifacts directory', './test-artifacts');
80
+ // Step 7: Skip video?
81
+ const skipVideo = depth === 'fast';
82
+ // Generate config file
83
+ const configContent = generateConfig({
84
+ name,
85
+ description,
86
+ domain,
87
+ appUrl,
88
+ userJourney,
89
+ artifactsDir,
90
+ models,
91
+ personaIds,
92
+ skipVideo,
93
+ });
94
+ const configPath = path.join(process.cwd(), 'quorumux.config.ts');
95
+ if (fs.existsSync(configPath)) {
96
+ const overwrite = await confirm('quorumux.config.ts already exists. Overwrite?', false);
97
+ if (!overwrite) {
98
+ console.log('\n Aborted. Existing config preserved.\n');
99
+ return;
100
+ }
101
+ }
102
+ fs.writeFileSync(configPath, configContent);
103
+ console.log('\n Config written to quorumux.config.ts');
104
+ console.log(` Selected ${personaIds.length} persona archetype(s): ${personaIds.join(', ')}`);
105
+ console.log(` Testing depth: ${depth}`);
106
+ console.log(`\n Next steps:`);
107
+ console.log(` 1. Place test artifacts in ${artifactsDir}/`);
108
+ console.log(` 2. Run: npx quorumux --dry-run`);
109
+ console.log(` 3. Run: npx quorumux\n`);
110
+ }
111
+ finally {
112
+ closePrompt();
113
+ }
114
+ }
115
+ async function resolveApiKeyStep() {
116
+ const existing = resolveApiKey();
117
+ if (existing) {
118
+ console.log(' API key found.\n');
119
+ return existing;
120
+ }
121
+ console.log(' No OpenRouter API key found.\n');
122
+ console.log(' Get one at: https://openrouter.ai/keys\n');
123
+ const key = await ask('Enter your OpenRouter API key');
124
+ if (!key) {
125
+ console.log('\n No key provided. You can set OPENROUTER_API_KEY later.\n');
126
+ return '';
127
+ }
128
+ const saveChoice = await select('Where should the key be stored?', [
129
+ {
130
+ label: 'Global config (~/.quorumux/config.json)',
131
+ value: 'global',
132
+ description: 'Convenient but stored in plaintext',
133
+ },
134
+ {
135
+ label: 'Show env var command (recommended)',
136
+ value: 'env',
137
+ description: 'More secure, add to your shell profile',
138
+ },
139
+ ]);
140
+ if (saveChoice === 'global') {
141
+ const config = loadGlobalConfig();
142
+ config.apiKey = key;
143
+ saveGlobalConfig(config);
144
+ process.env.OPENROUTER_API_KEY = key;
145
+ console.log('\n Saved to ~/.quorumux/config.json\n');
146
+ }
147
+ else {
148
+ console.log(`\n Add this to your shell profile (.zshrc, .bashrc, etc.):`);
149
+ console.log(` export OPENROUTER_API_KEY="${key}"\n`);
150
+ process.env.OPENROUTER_API_KEY = key;
151
+ }
152
+ return key;
153
+ }
154
+ async function selectPersonas() {
155
+ const bundle = await select('Which persona set?', [
156
+ { label: 'Quick (3)', value: 'quick', description: 'happy-path, mobile-first, accessibility' },
157
+ { label: 'Standard (5)', value: 'standard', description: '+ speed-runner, novice' },
158
+ {
159
+ label: 'Comprehensive (8)',
160
+ value: 'comprehensive',
161
+ description: '+ cautious-explorer, power-user, skeptic',
162
+ },
163
+ { label: 'Full (10)', value: 'full', description: 'All archetypes' },
164
+ ]);
165
+ // "Custom" would be handled via the "Other" auto-option in a real interactive UI,
166
+ // but for now bundles cover the main use cases
167
+ const ids = PERSONA_BUNDLES[bundle];
168
+ // Validate they all exist
169
+ getArchetypeSubset([...ids]);
170
+ return [...ids];
171
+ }
172
+ function generateConfig(input) {
173
+ const modelSpecToString = (spec, indent) => {
174
+ const parts = [`id: '${spec.id}'`, `name: '${spec.name}'`];
175
+ if (spec.maxTokens)
176
+ parts.push(`maxTokens: ${spec.maxTokens}`);
177
+ return `${indent}{ ${parts.join(', ')} }`;
178
+ };
179
+ const screenshotModels = input.models.screenshot
180
+ .map((m) => modelSpecToString(m, ' '))
181
+ .join(',\n');
182
+ const videoModel = modelSpecToString(input.models.video, ' ');
183
+ const synthesisModel = modelSpecToString(input.models.synthesis, ' ');
184
+ const personaArray = input.personaIds.map((id) => `'${id}'`).join(', ');
185
+ return `import type { QuorumUXConfig } from './src/types';
186
+
187
+ /**
188
+ * ${input.name} — QuorumUX Configuration
189
+ *
190
+ * Generated by \`quorumux init\`
191
+ */
192
+ const config: QuorumUXConfig = {
193
+ name: '${escapeStr(input.name)}',
194
+ description: '${escapeStr(input.description)}',
195
+ domain: '${escapeStr(input.domain)}',
196
+ appUrl: '${escapeStr(input.appUrl)}',
197
+ userJourney: '${escapeStr(input.userJourney)}',
198
+ artifactsDir: '${escapeStr(input.artifactsDir)}',
199
+
200
+ /** Persona archetypes selected during init */
201
+ personas: [${personaArray}],
202
+
203
+ models: {
204
+ screenshot: [
205
+ ${screenshotModels},
206
+ ],
207
+ video: ${videoModel},
208
+ synthesis: ${synthesisModel},
209
+ },
210
+
211
+ video: {
212
+ maxSizeMB: 20,
213
+ frameRate: 1,
214
+ },
215
+ };
216
+
217
+ export default config;
218
+ `;
219
+ }
220
+ function escapeStr(s) {
221
+ return s.replace(/\\/g, '\\\\').replace(/'/g, "\\'");
222
+ }
223
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACrF,OAAO,EAAc,eAAe,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAG9E,MAAM,OAAO,GAAG;IACd,EAAE,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,aAAa,EAAE;IAC9C,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE;IACtC,EAAE,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,YAAY,EAAE;IAC5C,EAAE,KAAK,EAAE,YAAY,EAAE,KAAK,EAAE,YAAY,EAAE;IAC5C,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE;IAChC,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE;IACpC,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,WAAW,EAAE;IAC1C,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE;CAC1B,CAAC;AAEX,MAAM,cAAc,GAKf;IACH;QACE,KAAK,EAAE,YAAY;QACnB,KAAK,EAAE,MAAM;QACb,WAAW,EAAE,gDAAgD;QAC7D,MAAM,EAAE;YACN,UAAU,EAAE,CAAC,EAAE,EAAE,EAAE,6BAA6B,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;YACnE,KAAK,EAAE,EAAE,EAAE,EAAE,6BAA6B,EAAE,IAAI,EAAE,QAAQ,EAAE;YAC5D,SAAS,EAAE,EAAE,EAAE,EAAE,6BAA6B,EAAE,IAAI,EAAE,QAAQ,EAAE;SACjE;KACF;IACD;QACE,KAAK,EAAE,gBAAgB;QACvB,KAAK,EAAE,UAAU;QACjB,WAAW,EAAE,0DAA0D;QACvE,MAAM,EAAE;YACN,UAAU,EAAE;gBACV,EAAE,EAAE,EAAE,6BAA6B,EAAE,IAAI,EAAE,QAAQ,EAAE;gBACrD,EAAE,EAAE,EAAE,6BAA6B,EAAE,IAAI,EAAE,QAAQ,EAAE;gBACrD,EAAE,EAAE,EAAE,0BAA0B,EAAE,IAAI,EAAE,OAAO,EAAE;aAClD;YACD,KAAK,EAAE,EAAE,EAAE,EAAE,6BAA6B,EAAE,IAAI,EAAE,QAAQ,EAAE;YAC5D,SAAS,EAAE,EAAE,EAAE,EAAE,2BAA2B,EAAE,IAAI,EAAE,MAAM,EAAE;SAC7D;KACF;IACD;QACE,KAAK,EAAE,gBAAgB;QACvB,KAAK,EAAE,UAAU;QACjB,WAAW,EAAE,uFAAuF;QACpG,MAAM,EAAE;YACN,UAAU,EAAE;gBACV,EAAE,EAAE,EAAE,6BAA6B,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE;gBACtE,EAAE,EAAE,EAAE,6BAA6B,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE;gBACtE,EAAE,EAAE,EAAE,0BAA0B,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE;aACnE;YACD,KAAK,EAAE,EAAE,EAAE,EAAE,6BAA6B,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,EAAE;YAC7E,SAAS,EAAE,EAAE,EAAE,EAAE,2BAA2B,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE;SAC/E;KACF;CACF,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,OAAO;IAC3B,OAAO,CAAC,GAAG,CAAC,gCAAgC,CAAC,CAAC;IAE9C,IAAI,CAAC;QACH,kBAAkB;QAClB,MAAM,MAAM,GAAG,MAAM,iBAAiB,EAAE,CAAC;QAEzC,yBAAyB;QACzB,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,cAAc,CAAC,CAAC;QACvC,MAAM,WAAW,GAAG,MAAM,GAAG,CAAC,sBAAsB,CAAC,CAAC;QACtD,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,6BAA6B,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;QACzE,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,kCAAkC,CAAC,CAAC;QAE7D,uBAAuB;QACvB,MAAM,WAAW,GAAG,MAAM,GAAG,CAAC,wCAAwC,CAAC,CAAC;QAExE,mBAAmB;QACnB,MAAM,UAAU,GAAG,MAAM,cAAc,EAAE,CAAC;QAE1C,wBAAwB;QACxB,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,gBAAgB,EAAE,cAAc,CAAC,CAAC;QAC7D,MAAM,MAAM,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,KAAK,CAAE,CAAC,MAAM,CAAC;QAErE,8BAA8B;QAC9B,MAAM,YAAY,GAAG,MAAM,GAAG,CAAC,qBAAqB,EAAE,kBAAkB,CAAC,CAAC;QAE1E,sBAAsB;QACtB,MAAM,SAAS,GAAG,KAAK,KAAK,MAAM,CAAC;QAEnC,uBAAuB;QACvB,MAAM,aAAa,GAAG,cAAc,CAAC;YACnC,IAAI;YACJ,WAAW;YACX,MAAM;YACN,MAAM;YACN,WAAW;YACX,YAAY;YACZ,MAAM;YACN,UAAU;YACV,SAAS;SACV,CAAC,CAAC;QAEH,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,oBAAoB,CAAC,CAAC;QAElE,IAAI,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;YAC9B,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,+CAA+C,EAAE,KAAK,CAAC,CAAC;YACxF,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,OAAO,CAAC,GAAG,CAAC,2CAA2C,CAAC,CAAC;gBACzD,OAAO;YACT,CAAC;QACH,CAAC;QAED,EAAE,CAAC,aAAa,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;QAE5C,OAAO,CAAC,GAAG,CAAC,0CAA0C,CAAC,CAAC;QACxD,OAAO,CAAC,GAAG,CAAC,cAAc,UAAU,CAAC,MAAM,0BAA0B,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC9F,OAAO,CAAC,GAAG,CAAC,oBAAoB,KAAK,EAAE,CAAC,CAAC;QACzC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;QAC/B,OAAO,CAAC,GAAG,CAAC,kCAAkC,YAAY,GAAG,CAAC,CAAC;QAC/D,OAAO,CAAC,GAAG,CAAC,oCAAoC,CAAC,CAAC;QAClD,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;IAC5C,CAAC;YAAS,CAAC;QACT,WAAW,EAAE,CAAC;IAChB,CAAC;AACH,CAAC;AAED,KAAK,UAAU,iBAAiB;IAC9B,MAAM,QAAQ,GAAG,aAAa,EAAE,CAAC;IACjC,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;QAClC,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;IAChD,OAAO,CAAC,GAAG,CAAC,4CAA4C,CAAC,CAAC;IAE1D,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,+BAA+B,CAAC,CAAC;IACvD,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,OAAO,CAAC,GAAG,CAAC,8DAA8D,CAAC,CAAC;QAC5E,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,MAAM,UAAU,GAAG,MAAM,MAAM,CAAC,iCAAiC,EAAE;QACjE;YACE,KAAK,EAAE,yCAAyC;YAChD,KAAK,EAAE,QAAiB;YACxB,WAAW,EAAE,oCAAoC;SAClD;QACD;YACE,KAAK,EAAE,oCAAoC;YAC3C,KAAK,EAAE,KAAc;YACrB,WAAW,EAAE,wCAAwC;SACtD;KACF,CAAC,CAAC;IAEH,IAAI,UAAU,KAAK,QAAQ,EAAE,CAAC;QAC5B,MAAM,MAAM,GAAG,gBAAgB,EAAE,CAAC;QAClC,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC;QACpB,gBAAgB,CAAC,MAAM,CAAC,CAAC;QACzB,OAAO,CAAC,GAAG,CAAC,kBAAkB,GAAG,GAAG,CAAC;QACrC,OAAO,CAAC,GAAG,CAAC,wCAAwC,CAAC,CAAC;IACxD,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,6DAA6D,CAAC,CAAC;QAC3E,OAAO,CAAC,GAAG,CAAC,kCAAkC,GAAG,KAAK,CAAC,CAAC;QACxD,OAAO,CAAC,GAAG,CAAC,kBAAkB,GAAG,GAAG,CAAC;IACvC,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC;AAED,KAAK,UAAU,cAAc;IAC3B,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,oBAAoB,EAAE;QAChD,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,OAAgB,EAAE,WAAW,EAAE,yCAAyC,EAAE;QACvG,EAAE,KAAK,EAAE,cAAc,EAAE,KAAK,EAAE,UAAmB,EAAE,WAAW,EAAE,wBAAwB,EAAE;QAC5F;YACE,KAAK,EAAE,mBAAmB;YAC1B,KAAK,EAAE,eAAwB;YAC/B,WAAW,EAAE,0CAA0C;SACxD;QACD,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,MAAe,EAAE,WAAW,EAAE,gBAAgB,EAAE;KAC9E,CAAC,CAAC;IAEH,kFAAkF;IAClF,+CAA+C;IAE/C,MAAM,GAAG,GAAG,eAAe,CAAC,MAAsC,CAAC,CAAC;IACpE,0BAA0B;IAC1B,kBAAkB,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;IAC7B,OAAO,CAAC,GAAG,GAAG,CAAC,CAAC;AAClB,CAAC;AAcD,SAAS,cAAc,CAAC,KAAkB;IACxC,MAAM,iBAAiB,GAAG,CAAC,IAAsD,EAAE,MAAc,EAAU,EAAE;QAC3G,MAAM,KAAK,GAAG,CAAC,QAAQ,IAAI,CAAC,EAAE,GAAG,EAAE,UAAU,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC;QAC3D,IAAI,IAAI,CAAC,SAAS;YAAE,KAAK,CAAC,IAAI,CAAC,cAAc,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;QAC/D,OAAO,GAAG,MAAM,KAAK,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;IAC5C,CAAC,CAAC;IAEF,MAAM,gBAAgB,GAAG,KAAK,CAAC,MAAM,CAAC,UAAU;SAC7C,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;SAC1C,IAAI,CAAC,KAAK,CAAC,CAAC;IAEf,MAAM,UAAU,GAAG,iBAAiB,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IACjE,MAAM,cAAc,GAAG,iBAAiB,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IAEzE,MAAM,YAAY,GAAG,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAExE,OAAO;;;KAGJ,KAAK,CAAC,IAAI;;;;;WAKJ,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC;kBACd,SAAS,CAAC,KAAK,CAAC,WAAW,CAAC;aACjC,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC;aACvB,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC;kBAClB,SAAS,CAAC,KAAK,CAAC,WAAW,CAAC;mBAC3B,SAAS,CAAC,KAAK,CAAC,YAAY,CAAC;;;eAGjC,YAAY;;;;EAIzB,gBAAgB;;aAEL,UAAU;iBACN,cAAc;;;;;;;;;;CAU9B,CAAC;AACF,CAAC;AAED,SAAS,SAAS,CAAC,CAAS;IAC1B,OAAO,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;AACvD,CAAC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Global Config Management (~/.quorumux/config.json)
3
+ *
4
+ * Handles global settings that persist across projects:
5
+ * - API key storage (env var preferred, global config as fallback)
6
+ * - Default model configuration
7
+ */
8
+ import { GlobalConfig } from '../types';
9
+ /** Load global config from ~/.quorumux/config.json. Returns empty config if not found. */
10
+ export declare function loadGlobalConfig(): GlobalConfig;
11
+ /** Save global config to ~/.quorumux/config.json. Creates ~/.quorumux/ if needed. */
12
+ export declare function saveGlobalConfig(config: GlobalConfig): void;
13
+ /**
14
+ * Resolve API key using the priority chain:
15
+ * 1. OPENROUTER_API_KEY env var
16
+ * 2. .env / .env.local in project dir
17
+ * 3. ~/.quorumux/config.json → apiKey
18
+ *
19
+ * Returns the key or undefined if not found anywhere.
20
+ */
21
+ export declare function resolveApiKey(): string | undefined;
22
+ //# sourceMappingURL=global.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"global.d.ts","sourceRoot":"","sources":["../../src/config/global.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAKxC,0FAA0F;AAC1F,wBAAgB,gBAAgB,IAAI,YAAY,CAW/C;AAED,qFAAqF;AACrF,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CAK3D;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,IAAI,MAAM,GAAG,SAAS,CAqBlD"}
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Global Config Management (~/.quorumux/config.json)
3
+ *
4
+ * Handles global settings that persist across projects:
5
+ * - API key storage (env var preferred, global config as fallback)
6
+ * - Default model configuration
7
+ */
8
+ import * as fs from 'fs';
9
+ import * as path from 'path';
10
+ const QUORUMUX_DIR = path.join(process.env.HOME || '~', '.quorumux');
11
+ const CONFIG_PATH = path.join(QUORUMUX_DIR, 'config.json');
12
+ /** Load global config from ~/.quorumux/config.json. Returns empty config if not found. */
13
+ export function loadGlobalConfig() {
14
+ if (!fs.existsSync(CONFIG_PATH)) {
15
+ return {};
16
+ }
17
+ try {
18
+ const raw = fs.readFileSync(CONFIG_PATH, 'utf-8');
19
+ return JSON.parse(raw);
20
+ }
21
+ catch {
22
+ return {};
23
+ }
24
+ }
25
+ /** Save global config to ~/.quorumux/config.json. Creates ~/.quorumux/ if needed. */
26
+ export function saveGlobalConfig(config) {
27
+ if (!fs.existsSync(QUORUMUX_DIR)) {
28
+ fs.mkdirSync(QUORUMUX_DIR, { recursive: true });
29
+ }
30
+ fs.writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2) + '\n');
31
+ }
32
+ /**
33
+ * Resolve API key using the priority chain:
34
+ * 1. OPENROUTER_API_KEY env var
35
+ * 2. .env / .env.local in project dir
36
+ * 3. ~/.quorumux/config.json → apiKey
37
+ *
38
+ * Returns the key or undefined if not found anywhere.
39
+ */
40
+ export function resolveApiKey() {
41
+ // 1. Env var (highest priority)
42
+ if (process.env.OPENROUTER_API_KEY) {
43
+ return process.env.OPENROUTER_API_KEY;
44
+ }
45
+ // 2. .env / .env.local in cwd
46
+ const envKey = readEnvFile('.env.local') || readEnvFile('.env');
47
+ if (envKey) {
48
+ process.env.OPENROUTER_API_KEY = envKey;
49
+ return envKey;
50
+ }
51
+ // 3. Global config
52
+ const globalConfig = loadGlobalConfig();
53
+ if (globalConfig.apiKey) {
54
+ process.env.OPENROUTER_API_KEY = globalConfig.apiKey;
55
+ return globalConfig.apiKey;
56
+ }
57
+ return undefined;
58
+ }
59
+ /** Read OPENROUTER_API_KEY from a dotenv file (simple parser, no deps) */
60
+ function readEnvFile(filename) {
61
+ const filePath = path.join(process.cwd(), filename);
62
+ if (!fs.existsSync(filePath))
63
+ return undefined;
64
+ try {
65
+ const content = fs.readFileSync(filePath, 'utf-8');
66
+ for (const line of content.split('\n')) {
67
+ const trimmed = line.trim();
68
+ if (trimmed.startsWith('#') || !trimmed.includes('='))
69
+ continue;
70
+ const eqIndex = trimmed.indexOf('=');
71
+ const key = trimmed.slice(0, eqIndex).trim();
72
+ if (key === 'OPENROUTER_API_KEY') {
73
+ let value = trimmed.slice(eqIndex + 1).trim();
74
+ // Strip surrounding quotes
75
+ if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith("'") && value.endsWith("'"))) {
76
+ value = value.slice(1, -1);
77
+ }
78
+ return value || undefined;
79
+ }
80
+ }
81
+ }
82
+ catch {
83
+ // Ignore read errors
84
+ }
85
+ return undefined;
86
+ }
87
+ //# sourceMappingURL=global.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"global.js","sourceRoot":"","sources":["../../src/config/global.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * QuorumUX CLI — Entry Point
4
+ *
5
+ * Subcommands:
6
+ * init Interactive project setup wizard
7
+ * run [opts] Run the analysis pipeline (default)
8
+ * --help Show help
9
+ *
10
+ * Orchestrates the 4-stage UX analysis pipeline:
11
+ * Stage 1: Extract frames and generate grids from videos
12
+ * Stage 2: Analyze screenshots with multiple AI models
13
+ * Stage 2b: Analyze videos for temporal insights (parallel with Stage 2)
14
+ * Stage 3: Synthesize analyses across models and test data
15
+ * Stage 4: Generate reports and GitHub issues
16
+ */
17
+ export type { QuorumUXConfig, ModelConfig, ModelSpec, VideoConfig, PersonaArchetype } from './types';
18
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;GAcG;AAQH,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,SAAS,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC"}