create-qa-architect 5.0.7 → 5.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/setup.js CHANGED
@@ -1,5 +1,68 @@
1
1
  #!/usr/bin/env node
2
2
 
3
+ /**
4
+ * DR26 fix: Architectural Refactoring Plan for setup.js (2201 lines)
5
+ *
6
+ * PRIORITY: This file should be split into focused modules to improve
7
+ * maintainability, testability, and reduce cognitive load.
8
+ *
9
+ * PROPOSED MODULE STRUCTURE (target: < 500 lines per module):
10
+ *
11
+ * 1. lib/commands/validate.js (~300 lines)
12
+ * - Validation command logic
13
+ * - Config validation workflows
14
+ * - Prelaunch validation integration
15
+ *
16
+ * 2. lib/commands/deps.js (~200 lines)
17
+ * - Dependency monitoring setup
18
+ * - Dependabot configuration
19
+ * - GitHub API integration calls
20
+ *
21
+ * 3. lib/commands/activate.js (~150 lines)
22
+ * - License activation flow
23
+ * - Interactive license prompts
24
+ * - License validation integration
25
+ *
26
+ * 4. lib/commands/setup-main.js (~800 lines)
27
+ * - Main setup orchestration
28
+ * - Template generation
29
+ * - File writing operations
30
+ * - Husky/lint-staged configuration
31
+ *
32
+ * 5. lib/setup-config.js (~200 lines)
33
+ * - Configuration merging logic
34
+ * - Package.json updates
35
+ * - Workflow injection helpers
36
+ *
37
+ * 6. setup.js (core CLI, ~200 lines)
38
+ * - Argument parsing
39
+ * - Command routing
40
+ * - Help/version display
41
+ * - Exit code handling
42
+ *
43
+ * MIGRATION CHECKLIST:
44
+ * - [ ] Extract validation command to lib/commands/validate.js
45
+ * - [ ] Extract deps command to lib/commands/deps.js
46
+ * - [ ] Extract license activation to lib/commands/activate.js
47
+ * - [ ] Extract main setup flow to lib/commands/setup-main.js
48
+ * - [ ] Extract config helpers to lib/setup-config.js
49
+ * - [ ] Update all tests to use new module structure
50
+ * - [ ] Verify all CLI commands still work (--help, --deps, --validate, etc.)
51
+ * - [ ] Update integration tests
52
+ * - [ ] Run full test suite and ensure 100% pass rate
53
+ *
54
+ * BENEFITS:
55
+ * - Easier to test individual commands
56
+ * - Reduced cognitive load when modifying specific features
57
+ * - Better code organization and discoverability
58
+ * - Easier to add new commands in the future
59
+ * - Faster development cycles (smaller files to navigate)
60
+ *
61
+ * BLOCKED BY: None (can be done incrementally)
62
+ * ESTIMATED EFFORT: 2-3 days with full test coverage
63
+ * RISK: Medium (need to ensure no regressions in CLI behavior)
64
+ */
65
+
3
66
  const fs = require('fs')
4
67
  const path = require('path')
5
68
  const { execSync } = require('child_process')
@@ -49,29 +112,23 @@ const {
49
112
  } = require('./config/defaults')
50
113
 
51
114
  // Enhanced validation capabilities
52
- const { ValidationRunner } = require('./lib/validation')
53
115
  const { validateQualityConfig } = require('./lib/config-validator')
54
116
 
55
117
  // Interactive mode capabilities
56
118
  const { InteractivePrompt } = require('./lib/interactive/prompt')
57
119
  const { runInteractiveFlow } = require('./lib/interactive/questions')
58
120
 
59
- // Basic dependency monitoring (Free Tier)
60
- const {
61
- hasNpmProject,
62
- generateBasicDependabotConfig,
63
- writeBasicDependabotConfig,
64
- } = require('./lib/dependency-monitoring-basic')
65
-
66
- // Premium dependency monitoring (Pro/Team/Enterprise Tiers)
67
- const {
68
- generatePremiumDependabotConfig,
69
- writePremiumDependabotConfig,
70
- } = require('./lib/dependency-monitoring-premium')
121
+ // Note: Dependency monitoring imports moved to ./lib/commands/deps.js
71
122
 
72
123
  // Custom template loading
73
124
  const { TemplateLoader } = require('./lib/template-loader')
74
125
 
126
+ // Command handlers (extracted for maintainability)
127
+ const {
128
+ handleValidationCommands,
129
+ handleDependencyMonitoring,
130
+ } = require('./lib/commands')
131
+
75
132
  // Licensing system
76
133
  const {
77
134
  getLicenseInfo,
@@ -91,6 +148,26 @@ const {
91
148
  getTestTierScripts,
92
149
  } = require('./lib/smart-strategy-generator')
93
150
 
151
+ // Quality Tools Generator (Lighthouse, size-limit, axe-core, commitlint, coverage)
152
+ const {
153
+ writeLighthouseConfig,
154
+ writeSizeLimitConfig,
155
+ writeCommitlintConfig,
156
+ writeCommitMsgHook,
157
+ writeAxeTestSetup,
158
+ getQualityToolsDependencies,
159
+ getQualityToolsScripts,
160
+ } = require('./lib/quality-tools-generator')
161
+
162
+ // Pre-Launch Validation (SEO, links, a11y, docs, env)
163
+ const {
164
+ writeValidationScripts,
165
+ writeEnvValidator,
166
+ writePa11yConfig,
167
+ getPrelaunchScripts,
168
+ getPrelaunchDependencies,
169
+ } = require('./lib/prelaunch-validator')
170
+
94
171
  // Telemetry (opt-in usage tracking)
95
172
  const { TelemetrySession, showTelemetryStatus } = require('./lib/telemetry')
96
173
 
@@ -103,7 +180,6 @@ const {
103
180
  // Critical setup enhancements (fixes production quality gaps)
104
181
  const {
105
182
  applyProductionQualityFixes,
106
- // generateEnhancedPreCommitHook,
107
183
  validateProjectSetup,
108
184
  } = require('./lib/setup-enhancements')
109
185
 
@@ -151,7 +227,12 @@ function injectCollaborationSteps(workflowContent, options = {}) {
151
227
  const safeReadDir = dir => {
152
228
  try {
153
229
  return fs.readdirSync(dir, { withFileTypes: true })
154
- } catch {
230
+ } catch (error) {
231
+ // Silent failure fix: Log non-ENOENT errors in DEBUG mode
232
+ // ENOENT is expected (dir doesn't exist), other errors may indicate issues
233
+ if (process.env.DEBUG && error?.code !== 'ENOENT') {
234
+ console.warn(`āš ļø Could not read directory ${dir}: ${error.message}`)
235
+ }
155
236
  return []
156
237
  }
157
238
  }
@@ -332,6 +413,7 @@ function parseArguments(rawArgs) {
332
413
  const isCheckMaturityMode = sanitizedArgs.includes('--check-maturity')
333
414
  const isValidateConfigMode = sanitizedArgs.includes('--validate-config')
334
415
  const isActivateLicenseMode = sanitizedArgs.includes('--activate-license')
416
+ const isPrelaunchMode = sanitizedArgs.includes('--prelaunch')
335
417
  const isDryRun = sanitizedArgs.includes('--dry-run')
336
418
  const ciProviderIndex = sanitizedArgs.findIndex(arg => arg === '--ci')
337
419
  const ciProvider =
@@ -372,6 +454,7 @@ function parseArguments(rawArgs) {
372
454
  isCheckMaturityMode,
373
455
  isValidateConfigMode,
374
456
  isActivateLicenseMode,
457
+ isPrelaunchMode,
375
458
  isDryRun,
376
459
  ciProvider,
377
460
  enableSlackAlerts,
@@ -410,6 +493,7 @@ function parseArguments(rawArgs) {
410
493
  isCheckMaturityMode,
411
494
  isValidateConfigMode,
412
495
  isActivateLicenseMode,
496
+ isPrelaunchMode,
413
497
  isDryRun,
414
498
  ciProvider,
415
499
  enableSlackAlerts,
@@ -535,6 +619,7 @@ VALIDATION OPTIONS:
535
619
  --validate-docs Run documentation validation only
536
620
  --validate-config Validate .qualityrc.json configuration file
537
621
  --check-maturity Detect and display project maturity level
622
+ --prelaunch Add pre-launch validation suite (SEO, links, a11y, docs)
538
623
 
539
624
  LICENSE, TELEMETRY & ERROR REPORTING:
540
625
  --license-status Show current license tier and available features
@@ -576,6 +661,9 @@ EXAMPLES:
576
661
  npx create-qa-architect@latest --check-maturity
577
662
  → Detect project maturity level (minimal, bootstrap, development, production-ready)
578
663
 
664
+ npx create-qa-architect@latest --prelaunch
665
+ → Add pre-launch validation: SEO (sitemap, robots, meta), links, a11y, docs
666
+
579
667
  npx create-qa-architect@latest --validate-config
580
668
  → Validate .qualityrc.json configuration file against JSON Schema
581
669
 
@@ -648,258 +736,8 @@ HELP:
648
736
  process.exit(0)
649
737
  }
650
738
 
651
- // Handle validation-only commands
652
- async function handleValidationCommands() {
653
- const validationOptions = {
654
- disableNpmAudit,
655
- disableGitleaks,
656
- disableActionlint,
657
- disableMarkdownlint,
658
- disableEslintSecurity,
659
- allowLatestGitleaks,
660
- }
661
- const validator = new ValidationRunner(validationOptions)
662
-
663
- if (isConfigSecurityMode) {
664
- try {
665
- await validator.runConfigSecurity()
666
- process.exit(0)
667
- } catch (error) {
668
- console.error(
669
- `\nāŒ Configuration security validation failed:\n${error.message}`
670
- )
671
- process.exit(1)
672
- }
673
- }
674
-
675
- if (isDocsValidationMode) {
676
- try {
677
- await validator.runDocumentationValidation()
678
- process.exit(0)
679
- } catch (error) {
680
- console.error(`\nāŒ Documentation validation failed:\n${error.message}`)
681
- process.exit(1)
682
- }
683
- }
684
-
685
- if (isComprehensiveMode || isValidationMode) {
686
- try {
687
- // Use parallel validation for 3-5x speedup (runs checks concurrently)
688
- await validator.runComprehensiveCheckParallel()
689
- process.exit(0)
690
- } catch (error) {
691
- console.error(`\nāŒ Comprehensive validation failed:\n${error.message}`)
692
- process.exit(1)
693
- }
694
- }
695
- }
696
-
697
- // Detect Python project
698
- function detectPythonProject(projectPath) {
699
- const pythonFiles = [
700
- 'pyproject.toml',
701
- 'requirements.txt',
702
- 'setup.py',
703
- 'Pipfile',
704
- ]
705
- return pythonFiles.some(file => fs.existsSync(path.join(projectPath, file)))
706
- }
707
-
708
- // Detect Rust project
709
- function detectRustProject(projectPath) {
710
- return fs.existsSync(path.join(projectPath, 'Cargo.toml'))
711
- }
712
-
713
- // Detect Ruby project
714
- function detectRubyProject(projectPath) {
715
- return fs.existsSync(path.join(projectPath, 'Gemfile'))
716
- }
717
-
718
- // Handle dependency monitoring (Free/Pro/Team/Enterprise)
719
- async function handleDependencyMonitoring() {
720
- const projectPath = process.cwd()
721
- const license = getLicenseInfo()
722
-
723
- // Detect all supported ecosystems (npm, Python, Ruby, Rust, etc.)
724
- const hasNpm = hasNpmProject(projectPath)
725
- const hasPython = detectPythonProject(projectPath)
726
- const hasRust = detectRustProject(projectPath)
727
- const hasRuby = detectRubyProject(projectPath)
728
-
729
- if (!hasNpm && !hasPython && !hasRust && !hasRuby) {
730
- console.error(
731
- 'āŒ No supported dependency file found (package.json, pyproject.toml, requirements.txt, Gemfile, Cargo.toml).'
732
- )
733
- console.log("šŸ’” Make sure you're in a directory with dependency files.")
734
- process.exit(1)
735
- }
736
-
737
- if (hasNpm) console.log('šŸ“¦ Detected: npm project')
738
- if (hasPython) console.log('šŸ Detected: Python project')
739
- if (hasRust) console.log('šŸ¦€ Detected: Rust project')
740
- if (hasRuby) console.log('šŸ’Ž Detected: Ruby project')
741
- console.log(`šŸ“‹ License tier: ${license.tier.toUpperCase()}`)
742
-
743
- // Enforce Free tier caps for dependency monitoring (counted as dependency PRs)
744
- if (license.tier === 'FREE') {
745
- const capCheck = checkUsageCaps('dependency-pr')
746
- if (!capCheck.allowed) {
747
- console.error(`āŒ ${capCheck.reason}`)
748
- console.error(
749
- ' Upgrade to Pro, Team, or Enterprise for unlimited runs: https://vibebuildlab.com/qa-architect'
750
- )
751
- process.exit(1)
752
- }
753
-
754
- const increment = incrementUsage('dependency-pr')
755
- const usage = increment.usage || capCheck.usage
756
- const caps = capCheck.caps
757
- if (usage && caps && caps.maxDependencyPRsPerMonth !== undefined) {
758
- console.log(
759
- `🧮 Usage: ${usage.dependencyPRs}/${caps.maxDependencyPRsPerMonth} dependency monitoring runs used this month`
760
- )
761
- }
762
- }
763
-
764
- const dependabotPath = path.join(projectPath, '.github', 'dependabot.yml')
765
-
766
- // Use premium or basic config based on license tier
767
- // Free beta ended with v4.1.1 - Premium features now require Pro/Team/Enterprise tier
768
- // Pro/Team/Enterprise: Framework-aware dependency monitoring with grouping
769
- // Free: Basic npm-only dependency monitoring
770
- const shouldUsePremium =
771
- license.tier === 'PRO' ||
772
- license.tier === 'TEAM' ||
773
- license.tier === 'ENTERPRISE'
774
-
775
- // Free tier only supports npm projects. Fail fast with a clear message.
776
- if (!shouldUsePremium && !hasNpm && (hasPython || hasRust || hasRuby)) {
777
- console.error(
778
- 'āŒ Dependency monitoring for this project requires a Pro, Team, or Enterprise license.'
779
- )
780
- console.error(
781
- ' Free tier supports npm projects only. Detected non-npm ecosystems.'
782
- )
783
- console.error(
784
- ' Options: add npm/package.json, or upgrade and re-run: npx create-qa-architect@latest --deps after activation.'
785
- )
786
- process.exit(1)
787
- }
788
-
789
- if (shouldUsePremium) {
790
- console.log(
791
- '\nšŸš€ Setting up framework-aware dependency monitoring (Premium)...\n'
792
- )
793
-
794
- const configData = generatePremiumDependabotConfig({
795
- projectPath,
796
- schedule: 'weekly',
797
- })
798
-
799
- if (configData) {
800
- const { ecosystems } = configData
801
- const ecosystemNames = Object.keys(ecosystems)
802
-
803
- if (ecosystemNames.length > 0) {
804
- console.log('šŸ” Detected ecosystems:')
805
-
806
- // Find primary ecosystem and total package count
807
- let primaryEcosystem = null
808
- ecosystemNames.forEach(ecoName => {
809
- const eco = ecosystems[ecoName]
810
- const frameworks = Object.keys(eco.detected || {})
811
- const totalPackages = frameworks.reduce((sum, fw) => {
812
- return sum + (eco.detected[fw]?.count || 0)
813
- }, 0)
814
-
815
- console.log(` • ${ecoName}: ${totalPackages} packages`)
816
-
817
- if (eco.primary) {
818
- primaryEcosystem = ecoName
819
- }
820
- })
821
-
822
- if (primaryEcosystem) {
823
- console.log(`\nšŸŽÆ Primary ecosystem: ${primaryEcosystem}`)
824
- }
825
- }
826
-
827
- writePremiumDependabotConfig(configData, dependabotPath)
828
- console.log(
829
- '\nāœ… Created .github/dependabot.yml with framework grouping'
830
- )
831
-
832
- console.log('\nšŸŽ‰ Premium dependency monitoring setup complete!')
833
- console.log('\nšŸ“‹ What was added (Pro Tier):')
834
- console.log(' • Framework-aware dependency grouping')
835
- console.log(
836
- ` • ${Object.keys(configData.config.updates[0].groups || {}).length} dependency groups created`
837
- )
838
- console.log(' • Intelligent update batching (reduces PRs by 60%+)')
839
- console.log(' • GitHub Actions dependency monitoring')
840
- }
841
- } else {
842
- console.log(
843
- '\nšŸ” Setting up basic dependency monitoring (Free Tier)...\n'
844
- )
845
-
846
- const dependabotConfig = generateBasicDependabotConfig({
847
- projectPath,
848
- schedule: 'weekly',
849
- })
850
-
851
- if (dependabotConfig) {
852
- writeBasicDependabotConfig(dependabotConfig, dependabotPath)
853
- console.log('āœ… Created .github/dependabot.yml')
854
- }
855
-
856
- console.log('\nšŸŽ‰ Basic dependency monitoring setup complete!')
857
- console.log('\nšŸ“‹ What was added (Free Tier):')
858
- console.log(' • Basic Dependabot configuration for npm packages')
859
- console.log(' • Weekly dependency updates on Monday 9am')
860
- console.log(' • GitHub Actions dependency monitoring')
861
-
862
- // Show upgrade message for premium features
863
- console.log('\nšŸ”’ Premium features now available:')
864
- console.log(
865
- ' āœ… Framework-aware package grouping (React, Vue, Angular)'
866
- )
867
- console.log(' • Coming soon: Multi-language support (Python, Rust, Go)')
868
- console.log(' • Planned: Advanced security audit workflows')
869
- console.log(' • Planned: Custom update schedules and notifications')
870
-
871
- showUpgradeMessage('Framework-Aware Dependency Grouping')
872
- }
873
-
874
- // Auto-enable Dependabot on GitHub if token available
875
- console.log('\nšŸ”§ Attempting to enable Dependabot on GitHub...')
876
- try {
877
- const { setupDependabot } = require('./lib/github-api')
878
- const result = await setupDependabot(projectPath, { verbose: true })
879
-
880
- if (result.success) {
881
- console.log('āœ… Dependabot alerts and security updates enabled!')
882
- } else if (result.errors.length > 0) {
883
- console.log('āš ļø Could not auto-enable Dependabot:')
884
- result.errors.forEach(err => console.log(` • ${err}`))
885
- console.log('\nšŸ’” Manual steps needed:')
886
- console.log(' • Go to GitHub repo → Settings → Code security')
887
- console.log(
888
- ' • Enable "Dependabot alerts" and "Dependabot security updates"'
889
- )
890
- }
891
- } catch (error) {
892
- console.log('āš ļø Could not auto-enable Dependabot:', error.message)
893
- console.log('\nšŸ’” Manual steps:')
894
- console.log(' • Enable Dependabot in GitHub repo settings')
895
- }
896
-
897
- console.log('\nšŸ’” Next steps:')
898
- console.log(' • Review and commit .github/dependabot.yml')
899
- console.log(
900
- ' • Dependabot will start monitoring weekly for dependency updates'
901
- )
902
- }
739
+ // Note: handleValidationCommands, handleDependencyMonitoring, detectPythonProject,
740
+ // detectRustProject, detectRubyProject are now imported from ./lib/commands
903
741
 
904
742
  // Handle license status command
905
743
  if (isLicenseStatusMode) {
@@ -969,6 +807,83 @@ HELP:
969
807
  })()
970
808
  }
971
809
 
810
+ // Handle pre-launch validation setup command
811
+ if (isPrelaunchMode) {
812
+ return (async () => {
813
+ try {
814
+ const projectPath = process.cwd()
815
+ const PackageJson = checkNodeVersionAndLoadPackageJson()
816
+ const pkgJson = await PackageJson.load(projectPath)
817
+ const license = getLicenseInfo()
818
+ const isPro =
819
+ license.tier === 'PRO' ||
820
+ license.tier === 'TEAM' ||
821
+ license.tier === 'ENTERPRISE'
822
+
823
+ console.log('\nšŸ“‹ Setting up pre-launch validation suite...\n')
824
+ console.log(` License tier: ${license.tier.toUpperCase()}`)
825
+
826
+ // Check feature availability
827
+ if (!hasFeature('prelaunchValidation')) {
828
+ console.error('āŒ Pre-launch validation requires a valid license.')
829
+ showUpgradeMessage('Pre-launch validation')
830
+ process.exit(1)
831
+ }
832
+
833
+ // Write validation scripts
834
+ const scriptsWritten = writeValidationScripts(projectPath)
835
+ console.log(` āœ… Created ${scriptsWritten.length} validation scripts`)
836
+
837
+ // Write pa11y config
838
+ writePa11yConfig(projectPath)
839
+ console.log(' āœ… Created .pa11yci config')
840
+
841
+ // Write env validator for Pro+
842
+ if (isPro && hasFeature('envValidation')) {
843
+ writeEnvValidator(projectPath)
844
+ console.log(' āœ… Created env vars validator (Pro)')
845
+ }
846
+
847
+ // Add scripts to package.json
848
+ const prelaunchScripts = getPrelaunchScripts(isPro)
849
+ const prelaunchDeps = getPrelaunchDependencies(isPro)
850
+
851
+ // Merge scripts
852
+ const existingScripts = pkgJson.content.scripts || {}
853
+ pkgJson.update({
854
+ scripts: { ...existingScripts, ...prelaunchScripts },
855
+ })
856
+
857
+ // Merge devDependencies
858
+ const existingDevDeps = pkgJson.content.devDependencies || {}
859
+ pkgJson.update({
860
+ devDependencies: { ...existingDevDeps, ...prelaunchDeps },
861
+ })
862
+
863
+ await pkgJson.save()
864
+
865
+ console.log('\nāœ… Pre-launch validation setup complete!\n')
866
+ console.log('Available scripts:')
867
+ console.log(' npm run validate:sitemap - Check sitemap.xml')
868
+ console.log(' npm run validate:robots - Check robots.txt')
869
+ console.log(' npm run validate:meta - Check meta tags')
870
+ console.log(' npm run validate:links - Check for broken links')
871
+ console.log(' npm run validate:a11y - Run accessibility audit')
872
+ console.log(' npm run validate:docs - Check documentation')
873
+ if (isPro) {
874
+ console.log(' npm run validate:env - Audit env vars (Pro)')
875
+ }
876
+ console.log(' npm run validate:prelaunch - Run all checks')
877
+ console.log('\nšŸ’” Run: npm install && npm run validate:prelaunch')
878
+
879
+ process.exit(0)
880
+ } catch (error) {
881
+ console.error('Pre-launch validation setup error:', error.message)
882
+ process.exit(1)
883
+ }
884
+ })()
885
+ }
886
+
972
887
  // Run validation commands if requested
973
888
  if (
974
889
  isValidationMode ||
@@ -979,13 +894,152 @@ HELP:
979
894
  // Handle validation commands and exit
980
895
  return (async () => {
981
896
  try {
982
- await handleValidationCommands()
897
+ await handleValidationCommands({
898
+ isConfigSecurityMode,
899
+ isDocsValidationMode,
900
+ isComprehensiveMode,
901
+ isValidationMode,
902
+ disableNpmAudit,
903
+ disableGitleaks,
904
+ disableActionlint,
905
+ disableMarkdownlint,
906
+ disableEslintSecurity,
907
+ allowLatestGitleaks,
908
+ })
983
909
  } catch (error) {
984
910
  console.error('Validation error:', error.message)
985
911
  process.exit(1)
986
912
  }
987
913
  })()
988
914
  } else {
915
+ /**
916
+ * Setup quality tools based on license tier
917
+ * - Lighthouse CI (Free: basic, Pro: with thresholds)
918
+ * - Bundle size limits (Pro only)
919
+ * - axe-core accessibility (Free)
920
+ * - Conventional commits (Free)
921
+ * - Coverage thresholds (Pro only)
922
+ */
923
+ async function setupQualityTools(_usesTypeScript, _packageJson) {
924
+ const qualitySpinner = showProgress('Setting up quality tools...')
925
+
926
+ try {
927
+ const projectPath = process.cwd()
928
+ const PackageJson = checkNodeVersionAndLoadPackageJson()
929
+ const pkgJson = await PackageJson.load(projectPath)
930
+ const addedTools = []
931
+
932
+ // Determine which features are available
933
+ const hasLighthouse = hasFeature('lighthouseCI')
934
+ const hasLighthouseThresholds = hasFeature('lighthouseThresholds')
935
+ const hasBundleSizeLimits = hasFeature('bundleSizeLimits')
936
+ const hasAxeAccessibility = hasFeature('axeAccessibility')
937
+ const hasConventionalCommits = hasFeature('conventionalCommits')
938
+ const hasCoverageThresholds = hasFeature('coverageThresholds')
939
+
940
+ // 1. Lighthouse CI - available to all, thresholds for Pro+
941
+ if (hasLighthouse) {
942
+ const lighthousePath = path.join(projectPath, 'lighthouserc.js')
943
+ if (!fs.existsSync(lighthousePath)) {
944
+ writeLighthouseConfig(projectPath, {
945
+ hasThresholds: hasLighthouseThresholds,
946
+ })
947
+ addedTools.push(
948
+ hasLighthouseThresholds
949
+ ? 'Lighthouse CI (with thresholds)'
950
+ : 'Lighthouse CI (basic)'
951
+ )
952
+ }
953
+ }
954
+
955
+ // 2. Bundle size limits - Pro only
956
+ if (hasBundleSizeLimits) {
957
+ if (!pkgJson.content['size-limit']) {
958
+ writeSizeLimitConfig(projectPath)
959
+ addedTools.push('Bundle size limits (size-limit)')
960
+ }
961
+ }
962
+
963
+ // 3. axe-core accessibility testing - available to all
964
+ if (hasAxeAccessibility) {
965
+ const axeTestPath = path.join(
966
+ projectPath,
967
+ 'tests',
968
+ 'accessibility.test.js'
969
+ )
970
+ if (!fs.existsSync(axeTestPath)) {
971
+ writeAxeTestSetup(projectPath)
972
+ addedTools.push('axe-core accessibility tests')
973
+ }
974
+ }
975
+
976
+ // 4. Conventional commits (commitlint) - available to all
977
+ if (hasConventionalCommits) {
978
+ const commitlintPath = path.join(projectPath, 'commitlint.config.js')
979
+ if (!fs.existsSync(commitlintPath)) {
980
+ writeCommitlintConfig(projectPath)
981
+ writeCommitMsgHook(projectPath)
982
+ addedTools.push('Conventional commits (commitlint)')
983
+ }
984
+ }
985
+
986
+ // 5. Coverage thresholds - Pro only (info message handled elsewhere)
987
+ if (hasCoverageThresholds) {
988
+ addedTools.push('Coverage thresholds (70% lines, 70% functions)')
989
+ }
990
+
991
+ // Add dependencies for enabled features
992
+ const deps = getQualityToolsDependencies({
993
+ lighthouse: hasLighthouse,
994
+ sizeLimit: hasBundleSizeLimits,
995
+ commitlint: hasConventionalCommits,
996
+ axeCore: hasAxeAccessibility,
997
+ })
998
+
999
+ // Add scripts for enabled features
1000
+ const scripts = getQualityToolsScripts({
1001
+ lighthouse: hasLighthouse,
1002
+ sizeLimit: hasBundleSizeLimits,
1003
+ axeCore: hasAxeAccessibility,
1004
+ coverage: hasCoverageThresholds,
1005
+ })
1006
+
1007
+ // Merge dependencies and scripts
1008
+ pkgJson.content.devDependencies = mergeDevDependencies(
1009
+ pkgJson.content.devDependencies || {},
1010
+ deps
1011
+ )
1012
+ pkgJson.content.scripts = mergeScripts(
1013
+ pkgJson.content.scripts || {},
1014
+ scripts
1015
+ )
1016
+ await pkgJson.save()
1017
+
1018
+ if (addedTools.length > 0) {
1019
+ qualitySpinner.succeed(
1020
+ `Quality tools configured: ${addedTools.length} tools`
1021
+ )
1022
+ addedTools.forEach(tool => console.log(` āœ… ${tool}`))
1023
+
1024
+ // Show Pro upsell for missing features
1025
+ if (!hasBundleSizeLimits || !hasCoverageThresholds) {
1026
+ console.log('\nšŸ’Ž Upgrade to Pro for additional quality tools:')
1027
+ if (!hasBundleSizeLimits) {
1028
+ console.log(' • Bundle size limits (size-limit)')
1029
+ }
1030
+ if (!hasCoverageThresholds) {
1031
+ console.log(' • Coverage threshold enforcement')
1032
+ }
1033
+ }
1034
+ } else {
1035
+ qualitySpinner.succeed('Quality tools already configured')
1036
+ }
1037
+ } catch (error) {
1038
+ qualitySpinner.warn('Could not set up some quality tools')
1039
+ console.warn('āš ļø Quality tools setup error:', error.message)
1040
+ }
1041
+ }
1042
+
989
1043
  // Normal setup flow
990
1044
  async function runMainSetup() {
991
1045
  // Record telemetry start event (opt-in only, fails silently)
@@ -1133,7 +1187,7 @@ HELP:
1133
1187
  const hasTypeScriptDependency = Boolean(
1134
1188
  (packageJson.devDependencies &&
1135
1189
  packageJson.devDependencies.typescript) ||
1136
- (packageJson.dependencies && packageJson.dependencies.typescript)
1190
+ (packageJson.dependencies && packageJson.dependencies.typescript)
1137
1191
  )
1138
1192
 
1139
1193
  const tsconfigCandidates = ['tsconfig.json', 'tsconfig.base.json']
@@ -1204,7 +1258,17 @@ HELP:
1204
1258
  }
1205
1259
 
1206
1260
  return false
1207
- } catch {
1261
+ } catch (error) {
1262
+ // Silent failure fix: Log unexpected errors in debug mode
1263
+ if (
1264
+ process.env.DEBUG &&
1265
+ error.code !== 'ENOENT' &&
1266
+ error.code !== 'EACCES'
1267
+ ) {
1268
+ console.warn(
1269
+ `āš ļø Could not scan ${dir} for Python files: ${error.message}`
1270
+ )
1271
+ }
1208
1272
  return false
1209
1273
  }
1210
1274
  }
@@ -1379,20 +1443,19 @@ HELP:
1379
1443
  })
1380
1444
  }
1381
1445
  } else {
1382
- // Config exists, validate it
1383
- // Temporarily disabled - debugging
1384
- // const validationResult = validateQualityConfig(qualityrcPath)
1385
- // if (!validationResult.valid) {
1386
- // console.warn(
1387
- // 'āš ļø Warning: Existing .qualityrc.json has validation issues:'
1388
- // )
1389
- // validationResult.errors.forEach(error => {
1390
- // console.warn(` - ${error}`)
1391
- // })
1392
- // console.warn(
1393
- // ' Setup will continue, but you may want to fix these issues.\n'
1394
- // )
1395
- // }
1446
+ // TD8 fix: Re-enabled validation (was disabled for debugging)
1447
+ const validationResult = validateQualityConfig(qualityrcPath)
1448
+ if (!validationResult.valid) {
1449
+ console.warn(
1450
+ 'āš ļø Warning: Existing .qualityrc.json has validation issues:'
1451
+ )
1452
+ validationResult.errors.forEach(error => {
1453
+ console.warn(` - ${error}`)
1454
+ })
1455
+ console.warn(
1456
+ ' Setup will continue, but you may want to fix these issues.\n'
1457
+ )
1458
+ }
1396
1459
  }
1397
1460
 
1398
1461
  // Load and merge templates (custom + defaults)
@@ -2007,6 +2070,9 @@ echo "āœ… Pre-push validation passed!"
2007
2070
  showUpgradeMessage('Smart Test Strategy')
2008
2071
  }
2009
2072
 
2073
+ // Quality Tools Integration
2074
+ await setupQualityTools(usesTypeScript, packageJson)
2075
+
2010
2076
  // Generate placeholder test file with helpful documentation
2011
2077
  const testsDir = path.join(process.cwd(), 'tests')
2012
2078
  const testExtension = usesTypeScript ? 'ts' : 'js'