ctx-cc 3.3.3 → 3.3.5

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/commands/qa.md ADDED
@@ -0,0 +1,625 @@
1
+ ---
2
+ name: ctx:qa
3
+ description: Full system QA - crawl every page, click every button, find all issues, create fix tasks. WCAG 2.1 AA compliant accessibility testing.
4
+ ---
5
+
6
+ <objective>
7
+ Run comprehensive end-to-end quality assurance on the entire application using industry best practices.
8
+
9
+ This command:
10
+ 1. Discovers all routes/pages in the app
11
+ 2. Crawls every page systematically
12
+ 3. Clicks every button, link, and interactive element
13
+ 4. Fills and submits every form
14
+ 5. Tests accessibility (WCAG 2.1 AA compliance)
15
+ 6. Tests responsive design (mobile, tablet, desktop)
16
+ 7. Checks keyboard navigation
17
+ 8. Monitors performance (slow requests, large assets)
18
+ 9. Creates a comprehensive QA report with traces
19
+ 10. Generates fix tasks organized by section/page
20
+ </objective>
21
+
22
+ <usage>
23
+ ```bash
24
+ /ctx:qa # Full system QA (all checks)
25
+ /ctx:qa --pages # List all discovered pages first
26
+ /ctx:qa --section "auth" # QA specific section only
27
+ /ctx:qa --a11y-only # Accessibility audit only (WCAG 2.1 AA)
28
+ /ctx:qa --visual-only # Visual regression only (3 viewports)
29
+ /ctx:qa --resume # Resume interrupted QA session
30
+ /ctx:qa --report # Show last QA report
31
+ ```
32
+ </usage>
33
+
34
+ <process>
35
+
36
+ ## Step 1: Discover Application Structure
37
+
38
+ ### 1.1 Read Codebase Map
39
+ ```bash
40
+ # Load route definitions from REPO-MAP
41
+ cat .ctx/REPO-MAP.md | grep -i "route\|page\|screen"
42
+ ```
43
+
44
+ ### 1.2 Discover Routes Programmatically
45
+ ```javascript
46
+ // For React/Next.js
47
+ mcp__playwright__browser_evaluate({
48
+ function: `
49
+ // Extract routes from React Router
50
+ const routes = [];
51
+ document.querySelectorAll('a[href^="/"]').forEach(a => {
52
+ routes.push(a.getAttribute('href'));
53
+ });
54
+ return [...new Set(routes)];
55
+ `
56
+ })
57
+
58
+ // For file-based routing (Next.js, Nuxt)
59
+ // Parse pages/ or app/ directory
60
+ ```
61
+
62
+ ### 1.3 Build Page Inventory
63
+ ```markdown
64
+ ## Discovered Pages
65
+
66
+ | # | Route | Type | Auth Required |
67
+ |---|-------|------|---------------|
68
+ | 1 | / | home | no |
69
+ | 2 | /login | auth | no |
70
+ | 3 | /dashboard | main | yes |
71
+ | 4 | /settings | settings | yes |
72
+ | 5 | /users | admin | yes |
73
+ ...
74
+ ```
75
+
76
+ Save to `.ctx/qa/PAGE_INVENTORY.md`
77
+
78
+ ## Step 2: Plan QA Sessions
79
+
80
+ ### 2.1 Group by Section
81
+ ```
82
+ Section: Authentication (3 pages)
83
+ - /login
84
+ - /register
85
+ - /forgot-password
86
+
87
+ Section: Dashboard (5 pages)
88
+ - /dashboard
89
+ - /dashboard/analytics
90
+ - /dashboard/reports
91
+ ...
92
+
93
+ Section: Settings (4 pages)
94
+ - /settings
95
+ - /settings/profile
96
+ - /settings/security
97
+ ...
98
+ ```
99
+
100
+ ### 2.2 Create QA Plan
101
+ ```markdown
102
+ ## QA Plan
103
+
104
+ Total Pages: {n}
105
+ Estimated Time: {pages * 2min}
106
+
107
+ ### Session 1: Public Pages (no auth)
108
+ - [ ] Home
109
+ - [ ] Login
110
+ - [ ] Register
111
+
112
+ ### Session 2: Dashboard
113
+ - [ ] Login first
114
+ - [ ] Dashboard home
115
+ - [ ] Analytics
116
+ ...
117
+ ```
118
+
119
+ Save to `.ctx/qa/QA_PLAN.md`
120
+
121
+ ## Step 3: Execute QA Per Page
122
+
123
+ For each page in inventory:
124
+
125
+ ### 3.1 Navigate
126
+ ```javascript
127
+ // Load credentials from .ctx/.env
128
+ const APP_URL = process.env.APP_URL;
129
+
130
+ mcp__playwright__browser_navigate({ url: `${APP_URL}${route}` });
131
+ ```
132
+
133
+ ### 3.2 Handle Authentication
134
+ ```javascript
135
+ // If login required and not logged in
136
+ if (requiresAuth && !isLoggedIn) {
137
+ // Navigate to login
138
+ mcp__playwright__browser_navigate({ url: `${APP_URL}/login` });
139
+
140
+ // Fill credentials from .ctx/.env
141
+ mcp__playwright__browser_type({
142
+ ref: 'email-input',
143
+ text: process.env.TEST_USER_EMAIL
144
+ });
145
+ mcp__playwright__browser_type({
146
+ ref: 'password-input',
147
+ text: process.env.TEST_USER_PASSWORD
148
+ });
149
+ mcp__playwright__browser_click({ ref: 'submit-button' });
150
+
151
+ // Return to target page
152
+ mcp__playwright__browser_navigate({ url: `${APP_URL}${route}` });
153
+ }
154
+ ```
155
+
156
+ ### 3.3 Take Initial Snapshot
157
+ ```javascript
158
+ mcp__playwright__browser_snapshot();
159
+ mcp__playwright__browser_take_screenshot({
160
+ filename: `.ctx/qa/screenshots/${route.replace(/\//g, '-')}-initial.png`
161
+ });
162
+ ```
163
+
164
+ ### 3.4 Check Console Errors
165
+ ```javascript
166
+ const messages = mcp__playwright__browser_console_messages({ level: 'error' });
167
+ if (messages.length > 0) {
168
+ issues.push({
169
+ type: 'console-error',
170
+ page: route,
171
+ errors: messages
172
+ });
173
+ }
174
+ ```
175
+
176
+ ### 3.5 Discover Interactive Elements
177
+ ```javascript
178
+ mcp__playwright__browser_evaluate({
179
+ function: `
180
+ const elements = [];
181
+
182
+ // Buttons
183
+ document.querySelectorAll('button').forEach((el, i) => {
184
+ elements.push({
185
+ type: 'button',
186
+ ref: el.getAttribute('data-ref') || 'button-' + i,
187
+ text: el.textContent.trim(),
188
+ disabled: el.disabled
189
+ });
190
+ });
191
+
192
+ // Links
193
+ document.querySelectorAll('a').forEach((el, i) => {
194
+ elements.push({
195
+ type: 'link',
196
+ ref: el.getAttribute('data-ref') || 'link-' + i,
197
+ text: el.textContent.trim(),
198
+ href: el.getAttribute('href')
199
+ });
200
+ });
201
+
202
+ // Forms
203
+ document.querySelectorAll('form').forEach((el, i) => {
204
+ elements.push({
205
+ type: 'form',
206
+ ref: el.getAttribute('data-ref') || 'form-' + i,
207
+ inputs: [...el.querySelectorAll('input, select, textarea')].map(input => ({
208
+ name: input.name,
209
+ type: input.type,
210
+ required: input.required
211
+ }))
212
+ });
213
+ });
214
+
215
+ // Inputs
216
+ document.querySelectorAll('input, select, textarea').forEach((el, i) => {
217
+ elements.push({
218
+ type: 'input',
219
+ ref: el.getAttribute('data-ref') || 'input-' + i,
220
+ name: el.name,
221
+ inputType: el.type
222
+ });
223
+ });
224
+
225
+ return elements;
226
+ `
227
+ })
228
+ ```
229
+
230
+ ### 3.6 Click Every Button
231
+ ```javascript
232
+ for (const button of buttons) {
233
+ if (button.disabled) continue;
234
+
235
+ try {
236
+ // Take before screenshot
237
+ mcp__playwright__browser_take_screenshot({
238
+ filename: `.ctx/qa/screenshots/${route}-btn-${button.ref}-before.png`
239
+ });
240
+
241
+ // Click
242
+ mcp__playwright__browser_click({
243
+ element: button.text,
244
+ ref: button.ref
245
+ });
246
+
247
+ // Wait for response
248
+ mcp__playwright__browser_wait_for({ time: 1 });
249
+
250
+ // Take after screenshot
251
+ mcp__playwright__browser_take_screenshot({
252
+ filename: `.ctx/qa/screenshots/${route}-btn-${button.ref}-after.png`
253
+ });
254
+
255
+ // Check for errors
256
+ const errors = mcp__playwright__browser_console_messages({ level: 'error' });
257
+ if (errors.length > 0) {
258
+ issues.push({
259
+ type: 'button-error',
260
+ page: route,
261
+ button: button.text,
262
+ errors: errors
263
+ });
264
+ }
265
+
266
+ // Navigate back if needed
267
+ mcp__playwright__browser_navigate_back();
268
+
269
+ } catch (e) {
270
+ issues.push({
271
+ type: 'button-crash',
272
+ page: route,
273
+ button: button.text,
274
+ error: e.message
275
+ });
276
+ }
277
+ }
278
+ ```
279
+
280
+ ### 3.7 Click Every Link
281
+ ```javascript
282
+ for (const link of links) {
283
+ // Skip external links
284
+ if (link.href.startsWith('http') && !link.href.includes(APP_URL)) continue;
285
+
286
+ try {
287
+ mcp__playwright__browser_click({ element: link.text, ref: link.ref });
288
+ mcp__playwright__browser_wait_for({ time: 1 });
289
+
290
+ // Check if navigation worked
291
+ const snapshot = mcp__playwright__browser_snapshot();
292
+ if (snapshot.includes('404') || snapshot.includes('not found')) {
293
+ issues.push({
294
+ type: 'broken-link',
295
+ page: route,
296
+ link: link.href,
297
+ text: link.text
298
+ });
299
+ }
300
+
301
+ // Go back
302
+ mcp__playwright__browser_navigate_back();
303
+
304
+ } catch (e) {
305
+ issues.push({
306
+ type: 'link-error',
307
+ page: route,
308
+ link: link.href,
309
+ error: e.message
310
+ });
311
+ }
312
+ }
313
+ ```
314
+
315
+ ### 3.8 Test Every Form
316
+ ```javascript
317
+ for (const form of forms) {
318
+ try {
319
+ // Fill with test data
320
+ for (const input of form.inputs) {
321
+ const testValue = getTestValue(input.type, input.name);
322
+ mcp__playwright__browser_type({
323
+ ref: input.ref,
324
+ text: testValue
325
+ });
326
+ }
327
+
328
+ // Submit
329
+ mcp__playwright__browser_click({ ref: form.submitButton });
330
+ mcp__playwright__browser_wait_for({ time: 2 });
331
+
332
+ // Check for validation errors or success
333
+ const snapshot = mcp__playwright__browser_snapshot();
334
+ const errors = mcp__playwright__browser_console_messages({ level: 'error' });
335
+
336
+ if (errors.length > 0) {
337
+ issues.push({
338
+ type: 'form-error',
339
+ page: route,
340
+ form: form.ref,
341
+ errors: errors
342
+ });
343
+ }
344
+
345
+ } catch (e) {
346
+ issues.push({
347
+ type: 'form-crash',
348
+ page: route,
349
+ form: form.ref,
350
+ error: e.message
351
+ });
352
+ }
353
+ }
354
+ ```
355
+
356
+ ### 3.9 Visual Checks
357
+ ```javascript
358
+ // Check for obvious visual issues
359
+ mcp__playwright__browser_evaluate({
360
+ function: `
361
+ const issues = [];
362
+
363
+ // Overlapping elements
364
+ // Missing images
365
+ document.querySelectorAll('img').forEach(img => {
366
+ if (!img.complete || img.naturalWidth === 0) {
367
+ issues.push({ type: 'broken-image', src: img.src });
368
+ }
369
+ });
370
+
371
+ // Tiny touch targets (WCAG)
372
+ document.querySelectorAll('button, a, input').forEach(el => {
373
+ const rect = el.getBoundingClientRect();
374
+ if (rect.width < 24 || rect.height < 24) {
375
+ issues.push({
376
+ type: 'small-touch-target',
377
+ element: el.tagName,
378
+ size: rect.width + 'x' + rect.height
379
+ });
380
+ }
381
+ });
382
+
383
+ return issues;
384
+ `
385
+ })
386
+ ```
387
+
388
+ ### 3.10 Save Page Results
389
+ ```markdown
390
+ ## Page: {route}
391
+
392
+ ### Summary
393
+ - Elements found: {count}
394
+ - Buttons clicked: {count}
395
+ - Links tested: {count}
396
+ - Forms submitted: {count}
397
+ - Issues found: {count}
398
+
399
+ ### Issues
400
+ | # | Type | Element | Description |
401
+ |---|------|---------|-------------|
402
+ | 1 | console-error | - | TypeError: undefined |
403
+ | 2 | broken-link | /old-page | 404 Not Found |
404
+ | 3 | button-crash | Delete | Unhandled promise |
405
+
406
+ ### Screenshots
407
+ - initial.png
408
+ - btn-submit-before.png
409
+ - btn-submit-after.png
410
+ ```
411
+
412
+ ## Step 4: Generate QA Report
413
+
414
+ After all pages tested:
415
+
416
+ ### 4.1 Aggregate Issues
417
+ ```markdown
418
+ # QA Report - {project_name}
419
+
420
+ **Date:** {ISO-8601}
421
+ **Pages Tested:** {total}
422
+ **Total Issues:** {count}
423
+
424
+ ## Summary by Severity
425
+
426
+ | Severity | Count |
427
+ |----------|-------|
428
+ | Critical | {n} |
429
+ | High | {n} |
430
+ | Medium | {n} |
431
+ | Low | {n} |
432
+
433
+ ## Summary by Type
434
+
435
+ | Type | Count |
436
+ |------|-------|
437
+ | Console Errors | {n} |
438
+ | Broken Links | {n} |
439
+ | Button Crashes | {n} |
440
+ | Form Errors | {n} |
441
+ | Visual Issues | {n} |
442
+ | A11y Issues | {n} |
443
+
444
+ ## Issues by Section
445
+
446
+ ### Section: Authentication
447
+ | Page | Issue | Severity | Description |
448
+ |------|-------|----------|-------------|
449
+ | /login | console-error | High | TypeError at line 45 |
450
+
451
+ ### Section: Dashboard
452
+ ...
453
+
454
+ ## Critical Issues (Fix First)
455
+ 1. [CRITICAL] /checkout - Payment form crashes on submit
456
+ 2. [CRITICAL] /api/users - Returns 500 error
457
+
458
+ ## All Screenshots
459
+ .ctx/qa/screenshots/
460
+ ```
461
+
462
+ Save to `.ctx/qa/QA_REPORT.md`
463
+
464
+ ## Step 5: Create Fix Tasks
465
+
466
+ ### 5.1 Group Issues by Section
467
+ ```markdown
468
+ ## Fix Tasks by Section
469
+
470
+ ### Section: Authentication (3 issues)
471
+
472
+ **Task A1: Fix login console errors**
473
+ - Page: /login
474
+ - Issues: 2 console errors
475
+ - Priority: High
476
+ - Files: src/auth/login.tsx
477
+
478
+ **Task A2: Fix forgot-password form**
479
+ - Page: /forgot-password
480
+ - Issues: Form doesn't submit
481
+ - Priority: High
482
+ - Files: src/auth/forgot-password.tsx
483
+
484
+ ### Section: Dashboard (5 issues)
485
+ ...
486
+ ```
487
+
488
+ ### 5.2 Create PRD Stories (Optional)
489
+ If `--create-stories` flag:
490
+ ```json
491
+ {
492
+ "stories": [
493
+ {
494
+ "id": "QA001",
495
+ "title": "Fix authentication section issues",
496
+ "type": "bug",
497
+ "acceptanceCriteria": [
498
+ "Login page has no console errors",
499
+ "Forgot password form submits successfully"
500
+ ],
501
+ "passes": false
502
+ }
503
+ ]
504
+ }
505
+ ```
506
+
507
+ ### 5.3 Update STATE.md
508
+ ```markdown
509
+ ## QA Results
510
+
511
+ Last Run: {timestamp}
512
+ Pages Tested: {n}
513
+ Issues Found: {n}
514
+
515
+ ### Fix Tasks Created
516
+ - [ ] QA001: Fix authentication issues (3 bugs)
517
+ - [ ] QA002: Fix dashboard issues (5 bugs)
518
+ - [ ] QA003: Fix checkout issues (2 bugs)
519
+
520
+ Next: Run `/ctx` to start fixing
521
+ ```
522
+
523
+ ## Step 6: Persistent State (Resume Support)
524
+
525
+ ### Save Progress
526
+ ```json
527
+ // .ctx/qa/SESSION.json
528
+ {
529
+ "sessionId": "qa-20240120-143000",
530
+ "status": "in_progress",
531
+ "totalPages": 25,
532
+ "completedPages": 12,
533
+ "currentPage": "/dashboard/analytics",
534
+ "issuesFound": 15,
535
+ "startedAt": "2024-01-20T14:30:00Z",
536
+ "lastUpdate": "2024-01-20T15:00:00Z"
537
+ }
538
+ ```
539
+
540
+ ### Resume
541
+ ```bash
542
+ /ctx:qa --resume
543
+ # Loads SESSION.json, continues from currentPage
544
+ ```
545
+
546
+ </process>
547
+
548
+ <test_data>
549
+
550
+ ## Smart Test Data Generation
551
+
552
+ For form testing, generate appropriate test data:
553
+
554
+ | Field Type | Test Value |
555
+ |------------|------------|
556
+ | email | `test-{uuid}@example.com` |
557
+ | password | `TestPass123!` |
558
+ | name | `Test User` |
559
+ | phone | `+1234567890` |
560
+ | address | `123 Test Street` |
561
+ | date | Today's date |
562
+ | number | `42` |
563
+ | url | `https://example.com` |
564
+ | textarea | `Lorem ipsum test content` |
565
+
566
+ For select/dropdown:
567
+ - Select first non-placeholder option
568
+
569
+ For checkbox/radio:
570
+ - Toggle to opposite state
571
+
572
+ </test_data>
573
+
574
+ <output>
575
+ ```
576
+ [CTX QA] Full System Quality Assurance
577
+
578
+ Discovering pages...
579
+ Found: 25 pages in 5 sections
580
+
581
+ Testing Section 1/5: Authentication
582
+ [✓] /login - 0 issues
583
+ [✓] /register - 1 issue (console warning)
584
+ [✗] /forgot-password - 2 issues (a11y: missing label)
585
+
586
+ Testing Section 2/5: Dashboard
587
+ [✓] /dashboard - 0 issues
588
+ [✗] /dashboard/analytics - 3 issues (touch target, contrast)
589
+ ...
590
+
591
+ Responsive Testing...
592
+ Mobile (375px): 25 pages tested
593
+ Tablet (768px): 25 pages tested
594
+ Desktop (1280px): 25 pages tested
595
+
596
+ Accessibility Audit (WCAG 2.1 AA)...
597
+ Perceivable: 45/49 pass
598
+ Operable: 38/39 pass
599
+ Understandable: 22/22 pass
600
+ Robust: 15/15 pass
601
+
602
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
603
+ QA COMPLETE
604
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
605
+
606
+ Pages Tested: 25 (75 viewport tests)
607
+ Duration: 1h 23m
608
+
609
+ Issues Found: 18
610
+ ├── Functional: 8 (2 critical, 4 high)
611
+ ├── Accessibility: 6 (1 critical, 3 high)
612
+ ├── Visual: 3 (1 high, 2 medium)
613
+ └── Performance: 1 (1 high)
614
+
615
+ WCAG 2.1 AA Score: 96%
616
+
617
+ Fix Tasks Created: 6
618
+
619
+ Report: .ctx/qa/QA_REPORT.md
620
+ Screenshots: .ctx/qa/screenshots/ (75 files)
621
+ Traces: .ctx/qa/traces/ (18 files)
622
+
623
+ Next: Run /ctx to start fixing critical issues
624
+ ```
625
+ </output>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ctx-cc",
3
- "version": "3.3.3",
3
+ "version": "3.3.5",
4
4
  "description": "CTX 3.3 (Continuous Task eXecution) - AI that learns your preferences. Learning system, predictive planning, self-healing deployments (Sentry/LogRocket), voice control for hands-free development.",
5
5
  "keywords": [
6
6
  "claude",