@champpaba/claude-agent-kit 2.3.0 → 2.5.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')
312
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
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
+ }
323
499
 
324
- for (const feature of detectedFeatures) {
325
- output(`\n🔍 Checking ${feature.name} against industry standards...`)
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
+ }
326
515
 
327
- const gaps = []
328
- const matches = []
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
+ }
329
531
 
330
- for (const standard of feature.standards) {
331
- const isMentioned = standard.keywords.some(kw =>
332
- designContent.toLowerCase().includes(kw)
333
- )
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
+ }
563
+
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
+ }
579
+
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
+ }
595
+
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
+ }
334
731
 
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
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)
780
+ return conflicts
781
+ }
360
782
 
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(``)
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
+ }
366
795
 
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
- })
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
+ })
373
802
 
374
- for (const [feature, reqs] of Object.entries(byFeature)) {
375
- output(` ${feature}:`)
376
- reqs.forEach(r => output(` - ${r}`))
377
- }
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
+ })
834
+ }
835
+
836
+ if (result.warnings.length > 0) {
837
+ content += `\n### ⚠️ Warnings\n\n`
838
+ result.warnings.forEach(w => {
839
+ content += `- ${w}\n`
840
+ })
453
841
  }
454
- // If C, just continue with warning logged
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
466
893
  }
467
894
 
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
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
+ ]
905
+ }
906
+
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
 
@@ -587,6 +1045,7 @@ if (resolvedLibraries.length === 0) {
587
1045
  }
588
1046
 
589
1047
  // 5. Generate best-practices files for resolved libraries
1048
+ // v2.5.0: Smart Topic Query - include other library names for cross-library integration docs
590
1049
  const bpDir = '.claude/contexts/domain/project/best-practices/'
591
1050
  const existingBp = fileExists(bpDir) ? listFiles(bpDir) : []
592
1051
 
@@ -598,22 +1057,53 @@ const newLibraries = resolvedLibraries.filter(lib => {
598
1057
 
599
1058
  if (newLibraries.length > 0) {
600
1059
  output(`\n📚 Generating Best Practices from Context7...`)
1060
+ output(` 💡 Using Smart Topic Query for cross-library integration docs`)
601
1061
 
602
1062
  // Create directory if needed
603
1063
  if (!fileExists(bpDir)) {
604
1064
  mkdir(bpDir)
605
1065
  }
606
1066
 
1067
+ // Collect all integration risks for summary
1068
+ const integrationRisks = []
1069
+
607
1070
  for (const lib of newLibraries) {
608
1071
  output(` 📖 Fetching ${lib.title} best practices...`)
609
1072
 
610
1073
  try {
1074
+ // v2.5.0: Smart Topic Query - include other library names in topic
1075
+ // WHY: This captures integration docs (e.g., "drizzle adapter" in auth.js docs)
1076
+ const otherLibNames = resolvedLibraries
1077
+ .filter(l => l.name !== lib.name)
1078
+ .map(l => l.name.toLowerCase())
1079
+ .slice(0, 5) // Limit to 5 to avoid topic overflow
1080
+ .join(', ')
1081
+
1082
+ const smartTopic = [
1083
+ 'best practices',
1084
+ 'patterns',
1085
+ 'anti-patterns',
1086
+ 'common mistakes',
1087
+ 'adapter', // Key for ORM + Auth integrations
1088
+ 'integration', // Key for multi-library setups
1089
+ 'schema', // Key for database + auth column naming
1090
+ 'configuration', // Key for setup requirements
1091
+ otherLibNames // Include other detected libraries
1092
+ ].filter(Boolean).join(', ')
1093
+
611
1094
  const docs = await mcp__context7__get_library_docs({
612
1095
  context7CompatibleLibraryID: lib.context7Id,
613
- topic: 'best practices, patterns, anti-patterns, common mistakes',
1096
+ topic: smartTopic,
614
1097
  mode: 'code'
615
1098
  })
616
1099
 
1100
+ // v2.5.0: Detect integration risks from docs content
1101
+ const risks = detectIntegrationRisks(docs, lib.name, resolvedLibraries)
1102
+ if (risks.length > 0) {
1103
+ integrationRisks.push(...risks)
1104
+ output(` ⚠️ Found ${risks.length} integration pattern(s) to review`)
1105
+ }
1106
+
617
1107
  const bpContent = generateBestPracticesFile(lib.title, docs, lib.context7Id)
618
1108
  const safeName = lib.name.toLowerCase().replace(/[^a-z0-9]/g, '-')
619
1109
  Write(`${bpDir}${safeName}.md`, bpContent)
@@ -624,6 +1114,13 @@ if (newLibraries.length > 0) {
624
1114
  }
625
1115
  }
626
1116
 
1117
+ // v2.5.0: Generate integration risk summary if any found
1118
+ if (integrationRisks.length > 0) {
1119
+ generateIntegrationRiskSummary(integrationRisks, bpDir, resolvedLibraries)
1120
+ output(`\n⚠️ Integration Risk Summary generated (${integrationRisks.length} items)`)
1121
+ output(` 📄 ${bpDir}INTEGRATION_RISKS.md`)
1122
+ }
1123
+
627
1124
  // Generate/update index.md
628
1125
  generateBestPracticesIndex(resolvedLibraries, changeId)
629
1126
  output(` ✅ index.md updated`)
@@ -1313,6 +1810,228 @@ function extractChecklist(docs: string): string {
1313
1810
 
1314
1811
  ---
1315
1812
 
1813
+ ### Helper: detectIntegrationRisks() - v2.5.0
1814
+
1815
+ > **Smart Risk Detection:** Scans Context7 docs for integration patterns that require attention.
1816
+ > **WHY:** Proactively catch integration requirements BEFORE implementation, not at runtime.
1817
+
1818
+ ```typescript
1819
+ function detectIntegrationRisks(
1820
+ docs: string,
1821
+ currentLib: string,
1822
+ allLibs: Array<{ name: string; title: string }>
1823
+ ): Array<{ library: string; risk: string; pattern: string; recommendation: string }> {
1824
+ const risks = []
1825
+ const docsLower = docs.toLowerCase()
1826
+
1827
+ // Integration risk patterns to detect
1828
+ const riskPatterns = [
1829
+ // Adapter patterns (ORM + Auth)
1830
+ {
1831
+ keywords: ['adapter', 'drizzleadapter', 'prismaadapter'],
1832
+ risk: 'Database adapter configuration required',
1833
+ pattern: 'adapter',
1834
+ recommendation: 'Verify adapter schema matches expected column names'
1835
+ },
1836
+ // Column naming patterns
1837
+ {
1838
+ keywords: ['column', 'columnname', 'snake_case', 'camelcase', 'mapping'],
1839
+ risk: 'Column naming convention mismatch possible',
1840
+ pattern: 'schema',
1841
+ recommendation: 'Check column naming between ORM schema and library expectations'
1842
+ },
1843
+ // Schema patterns
1844
+ {
1845
+ keywords: ['userstable', 'accountstable', 'sessionstable', 'schema'],
1846
+ risk: 'Custom table schema required',
1847
+ pattern: 'schema',
1848
+ recommendation: 'Ensure table schemas match library documentation exactly'
1849
+ },
1850
+ // Sync/Migration patterns
1851
+ {
1852
+ keywords: ['sync', 'migrate', 'migration', 'syncurl', 'embedded replica'],
1853
+ risk: 'Data synchronization setup required',
1854
+ pattern: 'sync',
1855
+ recommendation: 'Configure sync intervals and handle offline scenarios'
1856
+ },
1857
+ // Webhook patterns
1858
+ {
1859
+ keywords: ['webhook', 'webhookendpoint', 'webhooksecret'],
1860
+ risk: 'Webhook endpoint configuration required',
1861
+ pattern: 'webhook',
1862
+ recommendation: 'Set up webhook endpoints and verify signatures'
1863
+ },
1864
+ // API Key patterns
1865
+ {
1866
+ keywords: ['apikey', 'secretkey', 'authtoken', 'bearer'],
1867
+ risk: 'API credentials setup required',
1868
+ pattern: 'credentials',
1869
+ recommendation: 'Store credentials securely in environment variables'
1870
+ },
1871
+ // Lifecycle patterns
1872
+ {
1873
+ keywords: ['beforeall', 'afterall', 'beforeeach', 'aftereach', 'setup', 'teardown'],
1874
+ risk: 'Test lifecycle hooks required',
1875
+ pattern: 'lifecycle',
1876
+ recommendation: 'Implement proper setup/teardown in test configuration'
1877
+ }
1878
+ ]
1879
+
1880
+ for (const rp of riskPatterns) {
1881
+ const found = rp.keywords.some(kw => docsLower.includes(kw.toLowerCase()))
1882
+ if (found) {
1883
+ // Check if this risk involves other detected libraries
1884
+ const involvedLibs = allLibs
1885
+ .filter(l => l.name !== currentLib)
1886
+ .filter(l => docsLower.includes(l.name.toLowerCase()))
1887
+ .map(l => l.name)
1888
+
1889
+ risks.push({
1890
+ library: currentLib,
1891
+ risk: rp.risk,
1892
+ pattern: rp.pattern,
1893
+ recommendation: rp.recommendation,
1894
+ involvedLibraries: involvedLibs
1895
+ })
1896
+ }
1897
+ }
1898
+
1899
+ return risks
1900
+ }
1901
+ ```
1902
+
1903
+ ---
1904
+
1905
+ ### Helper: generateIntegrationRiskSummary() - v2.5.0
1906
+
1907
+ > **Risk Summary Output:** Creates INTEGRATION_RISKS.md with all detected cross-library concerns.
1908
+ > **WHY:** Agents can review this BEFORE implementation to avoid common integration mistakes.
1909
+
1910
+ ```typescript
1911
+ function generateIntegrationRiskSummary(
1912
+ risks: Array<{
1913
+ library: string
1914
+ risk: string
1915
+ pattern: string
1916
+ recommendation: string
1917
+ involvedLibraries?: string[]
1918
+ }>,
1919
+ bpDir: string,
1920
+ allLibs: Array<{ name: string; title: string }>
1921
+ ): void {
1922
+ // Group risks by pattern type
1923
+ const byPattern = {}
1924
+ for (const r of risks) {
1925
+ if (!byPattern[r.pattern]) byPattern[r.pattern] = []
1926
+ byPattern[r.pattern].push(r)
1927
+ }
1928
+
1929
+ const content = `# Integration Risk Summary
1930
+
1931
+ > **Generated:** ${new Date().toISOString().split('T')[0]}
1932
+ > **Template Version:** 2.5.0 - Smart Topic Query
1933
+ > **Detected Libraries:** ${allLibs.map(l => l.name).join(', ')}
1934
+
1935
+ ---
1936
+
1937
+ ## ⚠️ Review Before Implementation
1938
+
1939
+ The following integration patterns were detected from library documentation.
1940
+ **Agents should review these items in STEP 0 before writing code.**
1941
+
1942
+ ---
1943
+
1944
+ ${Object.entries(byPattern).map(([pattern, patternRisks]) => `
1945
+ ### ${pattern.toUpperCase()} Patterns
1946
+
1947
+ | Library | Risk | Recommendation |
1948
+ |---------|------|----------------|
1949
+ ${patternRisks.map(r => `| ${r.library} | ${r.risk} | ${r.recommendation} |`).join('\n')}
1950
+ ${patternRisks.some(r => r.involvedLibraries?.length > 0) ? `
1951
+ **Cross-library concerns:**
1952
+ ${patternRisks.filter(r => r.involvedLibraries?.length > 0).map(r => `- ${r.library} ↔ ${r.involvedLibraries.join(', ')}: ${r.risk}`).join('\n')}
1953
+ ` : ''}
1954
+ `).join('\n')}
1955
+
1956
+ ---
1957
+
1958
+ ## Quick Checklist
1959
+
1960
+ Before implementing integrations:
1961
+
1962
+ ${[...new Set(risks.map(r => r.recommendation))].map(rec => `- [ ] ${rec}`).join('\n')}
1963
+
1964
+ ---
1965
+
1966
+ **This file is auto-generated by /csetup v2.5.0**
1967
+ **Agents read this in STEP 0 alongside best-practices files**
1968
+ `
1969
+
1970
+ Write(`${bpDir}INTEGRATION_RISKS.md`, content)
1971
+ }
1972
+ ```
1973
+
1974
+ ---
1975
+
1976
+ ### Helper: generateBestPracticesIndex() - v2.5.0
1977
+
1978
+ > **Index File:** Creates index.md registry of all best practices files.
1979
+ > **v2.5.0:** Now includes INTEGRATION_RISKS.md if present.
1980
+
1981
+ ```typescript
1982
+ function generateBestPracticesIndex(
1983
+ resolvedLibraries: Array<{ name: string; title: string; context7Id: string }>,
1984
+ changeId: string
1985
+ ): void {
1986
+ const bpDir = '.claude/contexts/domain/project/best-practices/'
1987
+ const hasIntegrationRisks = fileExists(`${bpDir}INTEGRATION_RISKS.md`)
1988
+
1989
+ const content = `# Best Practices Index
1990
+
1991
+ > **Generated:** ${new Date().toISOString().split('T')[0]}
1992
+ > **Template Version:** 2.5.0 - Smart Topic Query
1993
+ > **Change:** ${changeId}
1994
+
1995
+ ---
1996
+
1997
+ ## 📚 Library Best Practices
1998
+
1999
+ | Library | File | Context7 ID |
2000
+ |---------|------|-------------|
2001
+ ${resolvedLibraries.map(lib => {
2002
+ const safeName = lib.name.toLowerCase().replace(/[^a-z0-9]/g, '-')
2003
+ return `| ${lib.title} | [${safeName}.md](./${safeName}.md) | \`${lib.context7Id}\` |`
2004
+ }).join('\n')}
2005
+
2006
+ ---
2007
+
2008
+ ${hasIntegrationRisks ? `## ⚠️ Integration Risks
2009
+
2010
+ Cross-library integration concerns detected. **Review before implementation.**
2011
+
2012
+ → [INTEGRATION_RISKS.md](./INTEGRATION_RISKS.md)
2013
+
2014
+ ---
2015
+
2016
+ ` : ''}## Usage
2017
+
2018
+ Agents read these files in **STEP 0** before implementation:
2019
+
2020
+ 1. Read \`index.md\` (this file) for overview
2021
+ 2. Read relevant \`{library}.md\` files for specific best practices
2022
+ ${hasIntegrationRisks ? '3. Read `INTEGRATION_RISKS.md` for cross-library concerns' : ''}
2023
+
2024
+ ---
2025
+
2026
+ **Auto-generated by /csetup v2.5.0**
2027
+ `
2028
+
2029
+ Write(`${bpDir}index.md`, content)
2030
+ }
2031
+ ```
2032
+
2033
+ ---
2034
+
1316
2035
  ### Step 3: Analyze Tasks
1317
2036
 
1318
2037
  **Parse tasks.md content and detect keywords:**