@champpaba/claude-agent-kit 2.2.1 → 2.4.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.
@@ -249,228 +249,686 @@ Continue anyway? (yes/no)
249
249
 
250
250
  ---
251
251
 
252
- ### Step 2.6: Feature Best Practice Analysis (v2.2.0)
252
+ ### Step 2.6: Adaptive Depth Research (v2.4.0)
253
253
 
254
- > **NEW:** Validate spec against industry standards BEFORE checking stack best practices
255
- > **Reference:** `.claude/lib/feature-best-practices.md`
254
+ > **NEW:** Dynamic research layers based on change complexity - replaces hardcoded feature detection
255
+ > **WHY:** Different changes need different research depth. A typo fix needs 0 layers, a healthcare portal needs 10+.
256
+ > **Output:** `openspec/changes/{changeId}/research-checklist.md`
256
257
 
257
- WHY: Stack best practices tell you "how to use React well", but Feature best practices tell you "what a good auth system needs". The feature layer is higher-level and informs whether your spec is complete.
258
+ **Key Principles:**
259
+ - Layer 1 is ALWAYS "Best Practice" (คนอื่นทำกันยังไง? / How do others do it?)
260
+ - Layer 2+ determined dynamically based on change context
261
+ - No fixed minimum or maximum - truly adaptive (0 to 10+ layers)
262
+ - Visual design (from /designsetup) is STATIC - this only handles Strategy (WHAT/WHERE)
263
+ - Warns if industry practice conflicts with user's design choices
258
264
 
259
265
  ```typescript
260
- output(`\n🔍 Analyzing Feature Best Practices...`)
261
-
262
- // 1. Detect features from proposal/tasks/design
263
- const combined = (proposalContent + ' ' + tasksContent + ' ' + designContent).toLowerCase()
264
-
265
- const featureDetection = {
266
- authentication: {
267
- keywords: ['login', 'auth', 'register', 'password', 'session', 'jwt', 'token', 'oauth'],
268
- tier: 1, // Blocking
269
- standards: [
270
- { name: 'Short-lived access token', keywords: ['jwt', 'access', '15', '30', 'min'], priority: 'required' },
271
- { name: 'Refresh token rotation', keywords: ['refresh', 'rotation', 'rotate'], priority: 'required' },
272
- { name: 'Secure token storage', keywords: ['httponly', 'cookie', 'secure'], priority: 'required' },
273
- { name: 'Token revocation', keywords: ['revoke', 'invalidate', 'logout'], priority: 'required' },
274
- { name: 'Rate limiting', keywords: ['rate', 'limit', 'throttle', 'attempt'], priority: 'required' },
275
- { name: 'Account lockout', keywords: ['lockout', 'lock', 'failed attempt'], priority: 'recommended' }
276
- ]
277
- },
278
- payment: {
279
- keywords: ['payment', 'stripe', 'checkout', 'billing', 'subscription'],
280
- tier: 1,
281
- standards: [
282
- { name: 'No card data on server', keywords: ['elements', 'checkout', 'client-side'], priority: 'required' },
283
- { name: 'Webhook signature verification', keywords: ['webhook', 'signature', 'verify'], priority: 'required' },
284
- { name: 'Idempotency keys', keywords: ['idempotency', 'idempotent'], priority: 'required' }
285
- ]
286
- },
287
- fileUpload: {
288
- keywords: ['upload', 'file', 'image', 's3', 'storage'],
289
- tier: 1,
290
- standards: [
291
- { name: 'File type validation', keywords: ['mime', 'type', 'validation', 'allowed'], priority: 'required' },
292
- { name: 'File size limits', keywords: ['size', 'limit', 'max'], priority: 'required' },
293
- { name: 'Filename sanitization', keywords: ['sanitize', 'filename', 'path'], priority: 'required' }
294
- ]
295
- },
296
- apiDesign: {
297
- keywords: ['api', 'endpoint', 'rest', 'graphql'],
298
- tier: 2, // Warning
299
- standards: [
300
- { name: 'Rate limiting', keywords: ['rate', 'limit'], priority: 'required' },
301
- { name: 'Input validation', keywords: ['validate', 'validation', 'zod', 'schema'], priority: 'required' },
302
- { name: 'Pagination', keywords: ['pagination', 'page', 'limit', 'offset'], priority: 'recommended' }
303
- ]
266
+ output(`\n🔬 Adaptive Depth Research Analysis...`)
267
+
268
+ // 1. Gather change context from all spec files
269
+ const proposalPath = `openspec/changes/${changeId}/proposal.md`
270
+ const tasksPath = `openspec/changes/${changeId}/tasks.md`
271
+ const designPath = `openspec/changes/${changeId}/design.md`
272
+
273
+ const proposal = fileExists(proposalPath) ? Read(proposalPath) : ''
274
+ const tasks = fileExists(tasksPath) ? Read(tasksPath) : ''
275
+ const design = fileExists(designPath) ? Read(designPath) : ''
276
+ const combined = (proposal + '\n' + tasks + '\n' + design).toLowerCase()
277
+
278
+ // 2. Analyze change characteristics using semantic understanding
279
+ const changeAnalysis = analyzeChangeCharacteristics(combined, proposal, tasks)
280
+
281
+ output(`\n📊 Change Analysis:`)
282
+ output(` Type: ${changeAnalysis.primaryType}`)
283
+ output(` Complexity: ${changeAnalysis.complexity}/10`)
284
+ output(` Risk Level: ${changeAnalysis.riskLevel}`)
285
+ output(` Target Audience: ${changeAnalysis.audience || 'Internal'}`)
286
+
287
+ // 3. Determine required research layers based on change characteristics
288
+ const requiredLayers = determineResearchLayers(changeAnalysis)
289
+
290
+ output(`\n📚 Research Layers Required: ${requiredLayers.length}`)
291
+
292
+ if (requiredLayers.length === 0) {
293
+ output(` ✅ No research needed - trivial change`)
294
+ output(` (Typo fix, debug log, simple badge, etc.)`)
295
+ } else {
296
+ requiredLayers.forEach((layer, idx) => {
297
+ output(` L${idx + 1}: ${layer.name}`)
298
+ output(` Focus: ${layer.focus}`)
299
+ output(` Questions: ${layer.questions.slice(0, 2).join(', ')}...`)
300
+ })
301
+ }
302
+
303
+ // 4. Execute research for each layer using Context7 + semantic analysis
304
+ const researchResults = []
305
+
306
+ for (const layer of requiredLayers) {
307
+ output(`\n🔍 Researching L${layer.order}: ${layer.name}...`)
308
+
309
+ const layerResult = await executeLayerResearch(layer, changeAnalysis)
310
+ researchResults.push(layerResult)
311
+
312
+ output(` ✅ Found ${layerResult.findings.length} key findings`)
313
+ if (layerResult.warnings.length > 0) {
314
+ layerResult.warnings.forEach(w => output(` ⚠️ ${w}`))
315
+ }
316
+ }
317
+
318
+ // 5. Check for conflicts with design system (if exists)
319
+ const tokensPath = 'design-system/tokens.json'
320
+ if (fileExists(tokensPath) && researchResults.length > 0) {
321
+ const tokens = JSON.parse(Read(tokensPath))
322
+ const conflicts = checkDesignConflicts(tokens, researchResults, changeAnalysis)
323
+
324
+ if (conflicts.length > 0) {
325
+ output(`\n⚠️ Design vs Industry Fit Conflicts:`)
326
+ conflicts.forEach(c => {
327
+ output(` - ${c.aspect}: Your design uses "${c.current}", but ${c.industry}`)
328
+ output(` Recommendation: ${c.recommendation}`)
329
+ })
330
+ output(`\n Note: User design choices take precedence. These are informational warnings.`)
304
331
  }
305
332
  }
306
333
 
307
- // 2. Find detected features
308
- const detectedFeatures = []
309
- for (const [featureName, config] of Object.entries(featureDetection)) {
310
- if (config.keywords.some(kw => combined.includes(kw))) {
311
- detectedFeatures.push({ name: featureName, ...config })
334
+ // 6. Generate research-checklist.md
335
+ const checklistPath = `openspec/changes/${changeId}/research-checklist.md`
336
+ const checklistContent = generateResearchChecklist(changeAnalysis, requiredLayers, researchResults)
337
+
338
+ Write(checklistPath, checklistContent)
339
+ output(`\n✅ Generated: ${checklistPath}`)
340
+
341
+ // Store for use by agents
342
+ const adaptiveResearch = {
343
+ layerCount: requiredLayers.length,
344
+ layers: requiredLayers.map(l => l.name),
345
+ complexity: changeAnalysis.complexity,
346
+ checklistPath: checklistPath
347
+ }
348
+ ```
349
+
350
+ #### Helper Functions
351
+
352
+ ```typescript
353
+ // Analyze change characteristics using semantic understanding
354
+ function analyzeChangeCharacteristics(combined, proposal, tasks) {
355
+ const analysis = {
356
+ primaryType: 'general',
357
+ complexity: 1,
358
+ riskLevel: 'LOW',
359
+ audience: 'internal',
360
+ domains: [],
361
+ features: [],
362
+ hasUI: false,
363
+ hasAPI: false,
364
+ hasDatabase: false,
365
+ hasPayment: false,
366
+ hasAuth: false,
367
+ hasCompliance: false,
368
+ hasSensitiveData: false,
369
+ isExternalFacing: false,
370
+ industryContext: null
371
+ }
372
+
373
+ // Detect primary type
374
+ if (/marketing|landing|hero|cta|conversion|sales/i.test(combined)) {
375
+ analysis.primaryType = 'marketing'
376
+ analysis.isExternalFacing = true
377
+ } else if (/dashboard|admin|management|analytics/i.test(combined)) {
378
+ analysis.primaryType = 'dashboard'
379
+ } else if (/api|endpoint|rest|graphql/i.test(combined)) {
380
+ analysis.primaryType = 'api'
381
+ } else if (/auth|login|register|password/i.test(combined)) {
382
+ analysis.primaryType = 'auth'
383
+ analysis.hasAuth = true
384
+ } else if (/database|schema|migration|model/i.test(combined)) {
385
+ analysis.primaryType = 'database'
386
+ analysis.hasDatabase = true
387
+ }
388
+
389
+ // Detect features and domains
390
+ if (/payment|stripe|billing|checkout|subscription/i.test(combined)) {
391
+ analysis.hasPayment = true
392
+ analysis.features.push('payment')
393
+ analysis.riskLevel = 'HIGH'
394
+ }
395
+ if (/health|medical|patient|hipaa|phi/i.test(combined)) {
396
+ analysis.hasCompliance = true
397
+ analysis.hasSensitiveData = true
398
+ analysis.domains.push('healthcare')
399
+ analysis.industryContext = 'healthcare'
400
+ analysis.riskLevel = 'HIGH'
401
+ }
402
+ if (/fintech|banking|finance|pci|financial/i.test(combined)) {
403
+ analysis.hasCompliance = true
404
+ analysis.domains.push('fintech')
405
+ analysis.industryContext = 'fintech'
406
+ analysis.riskLevel = 'HIGH'
407
+ }
408
+ if (/saas|multi-tenant|tenant/i.test(combined)) {
409
+ analysis.domains.push('saas')
410
+ analysis.features.push('multi-tenancy')
411
+ }
412
+ if (/ecommerce|e-commerce|cart|product|shop/i.test(combined)) {
413
+ analysis.domains.push('ecommerce')
414
+ analysis.isExternalFacing = true
415
+ }
416
+ if (/realtime|real-time|websocket|collaboration/i.test(combined)) {
417
+ analysis.features.push('realtime')
418
+ }
419
+
420
+ // Detect UI/API/Database
421
+ analysis.hasUI = /ui|page|component|form|button|modal/i.test(combined)
422
+ analysis.hasAPI = /api|endpoint|route|controller/i.test(combined)
423
+ analysis.hasDatabase = analysis.hasDatabase || /table|column|relation|index/i.test(combined)
424
+
425
+ // Detect audience
426
+ if (/b2c|consumer|user|customer/i.test(combined)) {
427
+ analysis.audience = 'consumer'
428
+ analysis.isExternalFacing = true
429
+ } else if (/b2b|enterprise|business/i.test(combined)) {
430
+ analysis.audience = 'business'
431
+ analysis.isExternalFacing = true
312
432
  }
433
+
434
+ // Calculate complexity (1-10)
435
+ let complexity = 1
436
+ if (analysis.features.length > 0) complexity += analysis.features.length
437
+ if (analysis.domains.length > 0) complexity += analysis.domains.length
438
+ if (analysis.hasCompliance) complexity += 2
439
+ if (analysis.hasPayment) complexity += 2
440
+ if (analysis.hasAuth) complexity += 1
441
+ if (analysis.isExternalFacing) complexity += 1
442
+ if (/integration|external api|third-party/i.test(combined)) complexity += 2
443
+
444
+ analysis.complexity = Math.min(complexity, 10)
445
+
446
+ // Adjust risk level
447
+ if (analysis.complexity >= 7 || analysis.hasCompliance || analysis.hasPayment) {
448
+ analysis.riskLevel = 'HIGH'
449
+ } else if (analysis.complexity >= 4 || analysis.hasAuth) {
450
+ analysis.riskLevel = 'MEDIUM'
451
+ }
452
+
453
+ return analysis
313
454
  }
314
455
 
315
- if (detectedFeatures.length > 0) {
316
- output(`\n📋 Features Detected:`)
317
- detectedFeatures.forEach(f => {
318
- output(` - ${f.name} (Tier ${f.tier}: ${f.tier === 1 ? 'Blocking' : 'Warning'})`)
456
+ // Determine research layers dynamically based on change characteristics
457
+ function determineResearchLayers(analysis) {
458
+ const layers = []
459
+ let order = 1
460
+
461
+ // Check for trivial changes (0 layers)
462
+ if (analysis.complexity <= 1 &&
463
+ !analysis.hasUI && !analysis.hasAPI && !analysis.hasDatabase &&
464
+ analysis.riskLevel === 'LOW') {
465
+ return [] // No research needed
466
+ }
467
+
468
+ // L1: Best Practice (ALWAYS for non-trivial changes)
469
+ layers.push({
470
+ order: order++,
471
+ name: 'Best Practice / Industry Standard',
472
+ focus: `How do others implement ${analysis.primaryType}?`,
473
+ questions: [
474
+ `What is the industry standard for ${analysis.primaryType}?`,
475
+ 'What are common patterns and anti-patterns?',
476
+ 'What are the key success factors?',
477
+ 'What are common failure modes?'
478
+ ],
479
+ searchTopics: [`${analysis.primaryType} best practices`, `${analysis.primaryType} patterns`]
319
480
  })
320
481
 
321
- // 3. For each Tier 1/2 feature, check spec against standards
322
- const allGaps = []
482
+ // L2+: Dynamic layers based on context
483
+
484
+ // Security layer (for auth, payment, sensitive data)
485
+ if (analysis.hasAuth || analysis.hasPayment || analysis.hasSensitiveData) {
486
+ layers.push({
487
+ order: order++,
488
+ name: 'Security Requirements',
489
+ focus: 'What security measures are required?',
490
+ questions: [
491
+ 'What authentication/authorization is needed?',
492
+ 'What data protection is required?',
493
+ 'What are common security vulnerabilities?',
494
+ 'What compliance requirements apply?'
495
+ ],
496
+ searchTopics: ['security best practices', `${analysis.primaryType} security`]
497
+ })
498
+ }
499
+
500
+ // Compliance layer (for regulated industries)
501
+ if (analysis.hasCompliance || analysis.industryContext) {
502
+ layers.push({
503
+ order: order++,
504
+ name: `${analysis.industryContext || 'Industry'} Compliance`,
505
+ focus: `What ${analysis.industryContext || 'industry'} regulations apply?`,
506
+ questions: [
507
+ 'What regulatory requirements must be met?',
508
+ 'What audit trails are needed?',
509
+ 'What data handling rules apply?',
510
+ 'What documentation is required?'
511
+ ],
512
+ searchTopics: [`${analysis.industryContext} compliance`, `${analysis.industryContext} regulations`]
513
+ })
514
+ }
515
+
516
+ // UX layer (for external-facing UI)
517
+ if (analysis.isExternalFacing && analysis.hasUI) {
518
+ layers.push({
519
+ order: order++,
520
+ name: 'User Experience Patterns',
521
+ focus: 'What UX patterns work for this audience?',
522
+ questions: [
523
+ 'What user journey is expected?',
524
+ 'What conversion patterns work?',
525
+ 'What accessibility requirements apply?',
526
+ 'What are user expectations?'
527
+ ],
528
+ searchTopics: [`${analysis.primaryType} UX`, `${analysis.audience} UX patterns`]
529
+ })
530
+ }
323
531
 
324
- for (const feature of detectedFeatures) {
325
- output(`\n🔍 Checking ${feature.name} against industry standards...`)
532
+ // Psychology layer (for marketing/sales)
533
+ if (analysis.primaryType === 'marketing' || /conversion|sales|cta/i.test(analysis.primaryType)) {
534
+ layers.push({
535
+ order: order++,
536
+ name: 'Conversion Psychology',
537
+ focus: 'What psychological triggers work?',
538
+ questions: [
539
+ 'What is the buyer awareness level?',
540
+ 'What pain points to address?',
541
+ 'What objections to overcome?',
542
+ 'What social proof is needed?'
543
+ ],
544
+ searchTopics: ['conversion psychology', 'landing page psychology']
545
+ })
546
+ }
547
+
548
+ // Content Strategy layer (for content-heavy pages)
549
+ if (analysis.primaryType === 'marketing' || /content|blog|documentation/i.test(analysis.primaryType)) {
550
+ layers.push({
551
+ order: order++,
552
+ name: 'Content Strategy',
553
+ focus: 'What content structure works?',
554
+ questions: [
555
+ 'What content hierarchy is effective?',
556
+ 'What tone and voice to use?',
557
+ 'What call-to-actions work?',
558
+ 'What content gaps exist?'
559
+ ],
560
+ searchTopics: ['content strategy', 'copywriting best practices']
561
+ })
562
+ }
326
563
 
327
- const gaps = []
328
- const matches = []
564
+ // Data Architecture layer (for database/data-intensive)
565
+ if (analysis.hasDatabase || /data|analytics|reporting/i.test(analysis.primaryType)) {
566
+ layers.push({
567
+ order: order++,
568
+ name: 'Data Architecture',
569
+ focus: 'What data patterns are appropriate?',
570
+ questions: [
571
+ 'What normalization level is appropriate?',
572
+ 'What indexing strategy is needed?',
573
+ 'What scaling considerations apply?',
574
+ 'What data integrity rules?'
575
+ ],
576
+ searchTopics: ['database design patterns', 'data architecture']
577
+ })
578
+ }
329
579
 
330
- for (const standard of feature.standards) {
331
- const isMentioned = standard.keywords.some(kw =>
332
- designContent.toLowerCase().includes(kw)
333
- )
580
+ // API Design layer (for API-focused changes)
581
+ if (analysis.hasAPI || analysis.primaryType === 'api') {
582
+ layers.push({
583
+ order: order++,
584
+ name: 'API Design',
585
+ focus: 'What API patterns are appropriate?',
586
+ questions: [
587
+ 'What API style is appropriate (REST/GraphQL)?',
588
+ 'What versioning strategy?',
589
+ 'What error handling patterns?',
590
+ 'What rate limiting/throttling?'
591
+ ],
592
+ searchTopics: ['API design best practices', 'REST API patterns']
593
+ })
594
+ }
334
595
 
335
- if (isMentioned) {
336
- matches.push(standard.name)
337
- } else if (standard.priority === 'required') {
338
- gaps.push({
339
- feature: feature.name,
340
- requirement: standard.name,
341
- priority: standard.priority,
342
- tier: feature.tier
596
+ // Multi-tenancy layer (for SaaS)
597
+ if (analysis.features.includes('multi-tenancy')) {
598
+ layers.push({
599
+ order: order++,
600
+ name: 'Multi-tenancy Patterns',
601
+ focus: 'What isolation and scaling patterns?',
602
+ questions: [
603
+ 'What data isolation model?',
604
+ 'What authentication per tenant?',
605
+ 'What resource limits?',
606
+ 'What billing model integration?'
607
+ ],
608
+ searchTopics: ['multi-tenant architecture', 'SaaS patterns']
609
+ })
610
+ }
611
+
612
+ // Real-time layer (for collaboration/live features)
613
+ if (analysis.features.includes('realtime')) {
614
+ layers.push({
615
+ order: order++,
616
+ name: 'Real-time Architecture',
617
+ focus: 'What real-time patterns are needed?',
618
+ questions: [
619
+ 'WebSocket vs SSE vs polling?',
620
+ 'What conflict resolution?',
621
+ 'What offline support?',
622
+ 'What scaling for connections?'
623
+ ],
624
+ searchTopics: ['real-time architecture', 'WebSocket patterns']
625
+ })
626
+ }
627
+
628
+ // Performance layer (for high-traffic or data-intensive)
629
+ if (analysis.isExternalFacing || analysis.complexity >= 6 ||
630
+ /performance|speed|optimization|cache/i.test(analysis.primaryType)) {
631
+ layers.push({
632
+ order: order++,
633
+ name: 'Performance Optimization',
634
+ focus: 'What performance patterns are needed?',
635
+ questions: [
636
+ 'What caching strategy?',
637
+ 'What lazy loading patterns?',
638
+ 'What CDN/edge considerations?',
639
+ 'What database optimization?'
640
+ ],
641
+ searchTopics: ['performance optimization', 'caching strategies']
642
+ })
643
+ }
644
+
645
+ // Integration layer (for external APIs/services)
646
+ if (/integration|external api|third-party|webhook/i.test(analysis.primaryType) ||
647
+ analysis.features.some(f => /payment|email|sms|notification/i.test(f))) {
648
+ layers.push({
649
+ order: order++,
650
+ name: 'Integration Patterns',
651
+ focus: 'What integration patterns are robust?',
652
+ questions: [
653
+ 'What retry/circuit breaker patterns?',
654
+ 'What error handling for external failures?',
655
+ 'What monitoring/alerting?',
656
+ 'What idempotency requirements?'
657
+ ],
658
+ searchTopics: ['integration patterns', 'API integration best practices']
659
+ })
660
+ }
661
+
662
+ // Testing Strategy layer (for complex/high-risk)
663
+ if (analysis.riskLevel === 'HIGH' || analysis.complexity >= 7) {
664
+ layers.push({
665
+ order: order++,
666
+ name: 'Testing Strategy',
667
+ focus: 'What testing coverage is needed?',
668
+ questions: [
669
+ 'What unit vs integration vs e2e balance?',
670
+ 'What edge cases to cover?',
671
+ 'What load/stress testing?',
672
+ 'What security testing?'
673
+ ],
674
+ searchTopics: ['testing strategy', `${analysis.primaryType} testing`]
675
+ })
676
+ }
677
+
678
+ return layers
679
+ }
680
+
681
+ // Execute research for a single layer using Claude's knowledge
682
+ // WHY: Domain knowledge (UX, DB design, security patterns) comes from Claude's training
683
+ // Stack knowledge (Prisma, React) comes from Context7 in Step 2.7
684
+ function executeLayerResearch(layer, changeAnalysis) {
685
+ const result = {
686
+ layer: layer.name,
687
+ findings: [],
688
+ recommendations: [],
689
+ warnings: [],
690
+ source: 'claude-knowledge'
691
+ }
692
+
693
+ // Claude generates best practices based on:
694
+ // - Layer context (what domain?)
695
+ // - Change analysis (what's being built?)
696
+ // - Questions to answer (what to research?)
697
+ //
698
+ // Claude's training includes:
699
+ // - UX: Nielsen Norman, Baymard Institute, Laws of UX
700
+ // - Database: Codd's normalization, indexing patterns
701
+ // - Security: OWASP, auth patterns, encryption
702
+ // - API: REST dissertation, versioning patterns
703
+ // - Architecture: distributed systems, caching, scaling
704
+
705
+ result.findings = generateDomainKnowledge(layer, changeAnalysis)
706
+ result.recommendations = generateRecommendations(layer, changeAnalysis)
707
+ result.warnings = checkForWarnings(layer, changeAnalysis)
708
+
709
+ return result
710
+ }
711
+
712
+ // Generate domain knowledge using Claude's reasoning
713
+ // This is where Claude applies its training to the specific change
714
+ function generateDomainKnowledge(layer, changeAnalysis) {
715
+ const findings = []
716
+
717
+ // Based on layer type, Claude will reason about best practices
718
+ // The actual content comes from Claude's response when /csetup runs
719
+
720
+ findings.push({
721
+ question: layer.questions[0],
722
+ // Claude fills this based on its knowledge when executing
723
+ analysis: `[Claude analyzes: ${layer.focus}]`,
724
+ bestPractices: [], // Claude lists industry standards
725
+ antiPatterns: [], // Claude lists what to avoid
726
+ tradeoffs: [] // Claude explains trade-offs
727
+ })
728
+
729
+ return findings
730
+ }
731
+
732
+ // Check for conflicts between design system and industry practices
733
+ function checkDesignConflicts(tokens, researchResults, changeAnalysis) {
734
+ const conflicts = []
735
+
736
+ // Only check for marketing/external-facing changes
737
+ if (!changeAnalysis.isExternalFacing) return conflicts
738
+
739
+ // Check color appropriateness for industry
740
+ if (tokens.colors && changeAnalysis.industryContext) {
741
+ const primaryColor = tokens.colors.primary
742
+
743
+ if (changeAnalysis.industryContext === 'healthcare') {
744
+ // Healthcare typically uses blue/green (trust, calm)
745
+ if (/red|orange|yellow/i.test(primaryColor)) {
746
+ conflicts.push({
747
+ aspect: 'Primary Color',
748
+ current: primaryColor,
749
+ industry: 'healthcare typically uses blue/green for trust and calm',
750
+ recommendation: 'Consider if bright colors are appropriate for healthcare context'
343
751
  })
344
752
  }
345
753
  }
346
754
 
347
- if (matches.length > 0) {
348
- output(` ✅ Matches: ${matches.join(', ')}`)
755
+ if (changeAnalysis.industryContext === 'fintech') {
756
+ // Fintech typically uses blue/green (trust, money)
757
+ if (/pink|purple|orange/i.test(primaryColor)) {
758
+ conflicts.push({
759
+ aspect: 'Primary Color',
760
+ current: primaryColor,
761
+ industry: 'fintech typically uses blue/green for trust and stability',
762
+ recommendation: 'Consider if playful colors fit financial services context'
763
+ })
764
+ }
349
765
  }
766
+ }
350
767
 
351
- if (gaps.length > 0) {
352
- output(` ❌ Gaps: ${gaps.map(g => g.requirement).join(', ')}`)
353
- allGaps.push(...gaps)
768
+ // Check animation appropriateness
769
+ if (tokens.animations && changeAnalysis.hasCompliance) {
770
+ if (tokens.animations.enableScrollAnimations) {
771
+ conflicts.push({
772
+ aspect: 'Scroll Animations',
773
+ current: 'enabled',
774
+ industry: 'compliance-heavy sites often minimize animations for accessibility',
775
+ recommendation: 'Ensure animations have reduced-motion alternatives'
776
+ })
354
777
  }
355
778
  }
356
779
 
357
- // 4. Handle gaps based on tier
358
- const tier1Gaps = allGaps.filter(g => g.tier === 1)
359
- const tier2Gaps = allGaps.filter(g => g.tier === 2)
360
-
361
- if (tier1Gaps.length > 0) {
362
- output(`\n⚠️ Security-Critical Gaps Found (Tier 1)`)
363
- output(``)
364
- output(`Your spec is missing these industry-standard requirements:`)
365
- output(``)
366
-
367
- // Group by feature
368
- const byFeature = {}
369
- tier1Gaps.forEach(g => {
370
- if (!byFeature[g.feature]) byFeature[g.feature] = []
371
- byFeature[g.feature].push(g.requirement)
372
- })
780
+ return conflicts
781
+ }
373
782
 
374
- for (const [feature, reqs] of Object.entries(byFeature)) {
375
- output(` ${feature}:`)
376
- reqs.forEach(r => output(` - ${r}`))
377
- }
783
+ // Generate research checklist markdown
784
+ function generateResearchChecklist(changeAnalysis, layers, results) {
785
+ let content = `# Research Checklist: ${changeAnalysis.primaryType}\n\n`
786
+ content += `> Generated by Adaptive Depth Research (v2.4.0)\n`
787
+ content += `> Complexity: ${changeAnalysis.complexity}/10 | Risk: ${changeAnalysis.riskLevel}\n\n`
788
+
789
+ if (layers.length === 0) {
790
+ content += `## ✅ No Research Required\n\n`
791
+ content += `This is a trivial change (complexity ${changeAnalysis.complexity}/10).\n`
792
+ content += `Proceed directly with implementation.\n`
793
+ return content
794
+ }
795
+
796
+ content += `## Summary\n\n`
797
+ content += `| Layer | Focus | Status |\n`
798
+ content += `|-------|-------|--------|\n`
799
+ layers.forEach((layer, idx) => {
800
+ content += `| L${idx + 1}: ${layer.name} | ${layer.focus} | ⏳ Pending |\n`
801
+ })
802
+
803
+ content += `\n---\n\n`
378
804
 
379
- output(``)
380
- output(`Options:`)
381
- output(` A) Update spec - Add missing requirements to design.md`)
382
- output(` B) Document skip - Record why these aren't needed (requires justification)`)
383
- output(` C) Continue anyway - Proceed with security gap (not recommended)`)
384
- output(``)
385
-
386
- const decision = await askUserQuestion({
387
- questions: [{
388
- question: 'How would you like to handle the security gaps?',
389
- header: 'Spec Gaps',
390
- options: [
391
- { label: 'A) Update spec', description: 'Add missing requirements to design.md (recommended)' },
392
- { label: 'B) Document skip', description: 'Record justification for skipping' },
393
- { label: 'C) Continue anyway', description: 'Proceed with gap (security risk)' }
394
- ],
395
- multiSelect: false
396
- }]
805
+ // Detail each layer
806
+ results.forEach((result, idx) => {
807
+ const layer = layers[idx]
808
+ content += `## L${idx + 1}: ${layer.name}\n\n`
809
+ content += `**Focus:** ${layer.focus}\n\n`
810
+
811
+ content += `### Key Questions\n\n`
812
+ layer.questions.forEach(q => {
813
+ content += `- [ ] ${q}\n`
397
814
  })
398
815
 
399
- if (decision.includes('A')) {
400
- // Generate suggested additions
401
- output(`\n📝 Add this to design.md:\n`)
402
- output(`\`\`\`markdown`)
403
- output(`### D{n}: Security Requirements (Industry Standard Alignment)`)
404
- output(``)
405
- output(`**Added based on industry best practices:**`)
406
- output(``)
407
- for (const [feature, reqs] of Object.entries(byFeature)) {
408
- output(`#### ${feature}`)
409
- reqs.forEach(r => output(`- ${r}`))
410
- }
411
- output(``)
412
- output(`**Source:** Feature Best Practice Validation`)
413
- output(`**Added:** ${new Date().toISOString().split('T')[0]}`)
414
- output(`\`\`\``)
415
- output(``)
416
- output(`Please update design.md and re-run /csetup.`)
417
- return
418
- } else if (decision.includes('B')) {
419
- // Document conscious skip
420
- output(`\n📝 Add this to design.md to document the skip:\n`)
421
- output(`\`\`\`markdown`)
422
- output(`### D{n}: Conscious Security Trade-offs`)
423
- output(``)
424
- output(`**Skipped requirements (with justification):**`)
425
- output(``)
426
- output(`| Requirement | Why Skipped | Risk Level | Mitigation |`)
427
- output(`|-------------|-------------|------------|------------|`)
428
- for (const gap of tier1Gaps) {
429
- output(`| ${gap.requirement} | [YOUR REASON] | [LOW/MED/HIGH] | [YOUR MITIGATION] |`)
430
- }
431
- output(``)
432
- output(`**Acknowledged by:** User decision in /csetup`)
433
- output(`**Date:** ${new Date().toISOString().split('T')[0]}`)
434
- output(`\`\`\``)
435
- output(``)
436
-
437
- const confirm = await askUserQuestion({
438
- questions: [{
439
- question: 'Confirm you will document this in design.md?',
440
- header: 'Confirm',
441
- options: [
442
- { label: 'Yes, continue', description: 'I will add documentation' },
443
- { label: 'Cancel', description: 'Go back and update spec' }
444
- ],
445
- multiSelect: false
446
- }]
816
+ if (result.findings.length > 0) {
817
+ content += `\n### Findings\n\n`
818
+ result.findings.forEach(f => {
819
+ content += `#### ${f.topic}\n\n`
820
+ if (Array.isArray(f.content)) {
821
+ f.content.forEach(point => content += `- ${point}\n`)
822
+ } else {
823
+ content += `${f.content}\n`
824
+ }
825
+ content += `\n*Source: ${f.source}*\n\n`
447
826
  })
827
+ }
448
828
 
449
- if (confirm.includes('Cancel')) {
450
- output(`\n❌ Setup cancelled. Please update design.md first.`)
451
- return
452
- }
829
+ if (result.recommendations.length > 0) {
830
+ content += `### Recommendations\n\n`
831
+ result.recommendations.forEach(r => {
832
+ content += `- ${r}\n`
833
+ })
453
834
  }
454
- // If C, just continue with warning logged
835
+
836
+ if (result.warnings.length > 0) {
837
+ content += `\n### ⚠️ Warnings\n\n`
838
+ result.warnings.forEach(w => {
839
+ content += `- ${w}\n`
840
+ })
841
+ }
842
+
843
+ content += `\n---\n\n`
844
+ })
845
+
846
+ // Add Content Guidelines section for marketing pages
847
+ if (changeAnalysis.primaryType === 'marketing' || changeAnalysis.isExternalFacing) {
848
+ content += `## 📝 Content Guidelines\n\n`
849
+ content += `> Claude generates these guidelines based on the change context.\n`
850
+ content += `> Use these as a starting point for content creation.\n\n`
851
+
852
+ content += `### Hero Section\n\n`
853
+ content += `**Headline Strategy:**\n`
854
+ content += `- Lead with primary pain point or aspiration\n`
855
+ content += `- 8-12 words, emotional trigger\n`
856
+ content += `- [Claude: Generate specific headline angle based on proposal]\n\n`
857
+
858
+ content += `**Subheadline:**\n`
859
+ content += `- Concrete benefit + emotional payoff\n`
860
+ content += `- 15-25 words\n`
861
+ content += `- [Claude: Generate based on value proposition]\n\n`
862
+
863
+ content += `**CTA:**\n`
864
+ content += `- Action verb + outcome\n`
865
+ content += `- [Claude: Generate based on user journey stage]\n\n`
866
+
867
+ content += `### Value Proposition\n\n`
868
+ content += `For each feature, translate to:\n`
869
+ content += `| Feature | Benefit | Emotional Payoff |\n`
870
+ content += `|---------|---------|------------------|\n`
871
+ content += `| [Technical] | [What user gets] | [How it makes them feel] |\n\n`
872
+
873
+ content += `### Social Proof\n\n`
874
+ content += `- Use specific results (numbers, timeframes)\n`
875
+ content += `- Match testimonials to target audience\n`
876
+ content += `- Include trust signals (logos, certifications)\n\n`
877
+
878
+ content += `---\n\n`
455
879
  }
456
880
 
457
- if (tier2Gaps.length > 0) {
458
- output(`\n⚠️ Recommendations (Tier 2 - Non-blocking):`)
459
- tier2Gaps.forEach(g => {
460
- output(` - ${g.feature}: ${g.requirement}`)
461
- })
462
- output(` Continuing with setup...`)
881
+ content += `## Agent Instructions\n\n`
882
+ content += `When implementing this change, agents should:\n\n`
883
+ content += `1. Review each layer's findings before starting\n`
884
+ content += `2. Check off questions as they are addressed\n`
885
+ content += `3. Follow recommendations where applicable\n`
886
+ content += `4. Address warnings or document exceptions\n`
887
+
888
+ if (changeAnalysis.primaryType === 'marketing' || changeAnalysis.isExternalFacing) {
889
+ content += `5. Use Content Guidelines section for copy direction\n`
463
890
  }
464
- } else {
465
- output(`\n✅ No security-critical features detected`)
891
+
892
+ return content
893
+ }
894
+
895
+ // Helper: Generate recommendations based on layer and context
896
+ // Claude fills in actual recommendations when executing /csetup
897
+ function generateRecommendations(layer, changeAnalysis) {
898
+ // These are prompts for Claude to expand with actual knowledge
899
+ // When /csetup runs, Claude will provide specific recommendations
900
+
901
+ return [
902
+ `[Claude: Based on ${layer.name} best practices for ${changeAnalysis.primaryType}]`,
903
+ `[Claude: Specific to this change's context and requirements]`
904
+ ]
466
905
  }
467
906
 
468
- // Store feature analysis for later use
469
- const featureAnalysis = {
470
- detected: detectedFeatures.map(f => f.name),
471
- tier1Gaps: tier1Gaps || [],
472
- tier2Gaps: tier2Gaps || [],
473
- validated: true
907
+ // Helper: Check for potential warnings based on layer and context
908
+ function checkForWarnings(layer, changeAnalysis) {
909
+ const warnings = []
910
+
911
+ // Risk-based warnings
912
+ if (changeAnalysis.riskLevel === 'HIGH') {
913
+ warnings.push(`HIGH risk change - review ${layer.name} carefully before deployment`)
914
+ }
915
+
916
+ // Compliance warnings
917
+ if (layer.name.includes('Compliance') && changeAnalysis.hasCompliance) {
918
+ warnings.push(`Regulatory compliance required - ensure all ${changeAnalysis.industryContext} requirements are met`)
919
+ }
920
+
921
+ // Payment warnings
922
+ if (changeAnalysis.hasPayment) {
923
+ warnings.push('Payment integration - ensure PCI compliance requirements are met')
924
+ }
925
+
926
+ // Security warnings
927
+ if (layer.name.includes('Security') && changeAnalysis.hasSensitiveData) {
928
+ warnings.push('Sensitive data handling - ensure proper encryption and access controls')
929
+ }
930
+
931
+ return warnings
474
932
  }
475
933
  ```
476
934