create-qa-architect 5.0.1 โ†’ 5.0.6

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.
@@ -126,6 +126,7 @@ class TemplateLoader {
126
126
  * // Only loads from whitelisted dirs: config/, .github/, lib/
127
127
  */
128
128
  async loadTemplates(dir, baseDir = dir, isPackageDir = false) {
129
+ /** @type {Record<string, string>} */
129
130
  const templates = {}
130
131
 
131
132
  try {
@@ -177,6 +178,7 @@ class TemplateLoader {
177
178
  * @returns {Promise<Object>} Merged template map
178
179
  */
179
180
  async mergeTemplates(customDir, defaultsDir) {
181
+ /** @type {Record<string, string>} */
180
182
  const merged = {}
181
183
 
182
184
  // Load defaults first (from package directory - restrict to known template dirs)
package/lib/ui-helpers.js CHANGED
@@ -55,7 +55,8 @@ function showProgress(message) {
55
55
 
56
56
  // Try to use ora for interactive terminals
57
57
  try {
58
- const ora = require('ora')
58
+ const oraImport = require('ora')
59
+ const ora = /** @type {any} */ (oraImport.default || oraImport)
59
60
  return ora(message).start()
60
61
  } catch {
61
62
  // Fallback if ora not installed (graceful degradation)
@@ -1,5 +1,9 @@
1
1
  'use strict'
2
2
 
3
+ /**
4
+ * @typedef {Error & {code?: string}} ErrWithCode
5
+ */
6
+
3
7
  /**
4
8
  * Base Validator Class
5
9
  * Provides common error handling, state management, and validation patterns
@@ -81,7 +85,7 @@ class BaseValidator {
81
85
 
82
86
  /**
83
87
  * Format error message for user
84
- * @param {Error} error - The error object
88
+ * @param {ErrWithCode} error - The error object
85
89
  * @param {string} context - The context
86
90
  * @returns {string} Formatted error message
87
91
  */
@@ -14,6 +14,7 @@ class CacheManager {
14
14
  options.cacheDir || path.join(process.cwd(), '.create-qa-architect-cache')
15
15
  this.ttl = options.ttl || 24 * 60 * 60 * 1000 // Default: 24 hours in milliseconds
16
16
  this.enabled = options.enabled !== false // Enable by default
17
+ this.verbose = Boolean(options.verbose)
17
18
 
18
19
  // Ensure cache directory exists
19
20
  if (this.enabled) {
@@ -10,16 +10,17 @@ const { showProgress } = require('../ui-helpers')
10
10
 
11
11
  // Pinned gitleaks version for reproducible security scanning
12
12
  const GITLEAKS_VERSION = '8.28.0'
13
- // Real SHA256 checksums from https://github.com/gitleaks/gitleaks/releases/tag/v8.28.0
13
+ // SHA256 checksums of EXTRACTED BINARIES from gitleaks v8.28.0 release
14
+ // Note: These are checksums of the binary itself, not the tarball/zip archives
14
15
  const GITLEAKS_CHECKSUMS = {
15
16
  'linux-x64':
16
- 'a65b5253807a68ac0cafa4414031fd740aeb55f54fb7e55f386acb52e6a840eb',
17
+ '5fd1b3b0073269484d40078662e921d07427340ab9e6ed526ccd215a565b3298',
17
18
  'darwin-x64':
18
- 'edf5a507008b0d2ef4959575772772770586409c1f6f74dabf19cbe7ec341ced',
19
+ 'cf09ad7a85683d90221db8324f036f23c8c29107145e1fc4a0dffbfa9e89c09a',
19
20
  'darwin-arm64':
20
21
  '5588b5d942dffa048720f7e6e1d274283219fb5722a2c7564d22e83ba39087d7',
21
22
  'win32-x64':
22
- 'da6458e8864af553807de1c46a7a8eac0880bd6b99ba56288e87e86a45af884f',
23
+ '54230c22688d19939f316cd3e2e040cd067ece40a3a8c5b684e5110c62ecbf52',
23
24
  }
24
25
 
25
26
  /**
@@ -75,7 +75,7 @@ class ValidationFactory {
75
75
 
76
76
  /**
77
77
  * Run all validators
78
- * @returns {object} Validation results
78
+ * @returns {Promise<object>} Validation results
79
79
  */
80
80
  async validateAll() {
81
81
  const results = {
package/lib/yaml-utils.js CHANGED
@@ -82,17 +82,22 @@ function convertToYaml(obj, indent = 0) {
82
82
  if (Array.isArray(obj)) {
83
83
  obj.forEach(item => {
84
84
  if (typeof item === 'object' && item !== null) {
85
- // For objects in arrays, handle first property inline with dash, rest indented
86
- const itemYaml = convertToYaml(item, indent + 2)
87
- const lines = itemYaml.split('\n').filter(line => line.trim())
88
- if (lines.length > 0) {
89
- // First property goes inline with the dash
90
- yaml += `${spaces}- ${lines[0].trim()}\n`
91
- // Additional properties are properly indented
92
- for (let i = 1; i < lines.length; i++) {
93
- yaml += `${spaces} ${lines[i].trim()}\n`
85
+ // For objects in arrays, prefix first line with "- " and indent rest
86
+ const entries = Object.entries(item)
87
+ entries.forEach(([key, value], idx) => {
88
+ const safeKey = formatYamlValue(key)
89
+ const prefix = idx === 0 ? `${spaces}- ` : `${spaces} `
90
+
91
+ if (Array.isArray(value)) {
92
+ yaml += `${prefix}${safeKey}:\n`
93
+ yaml += convertToYaml(value, indent + 4)
94
+ } else if (typeof value === 'object' && value !== null) {
95
+ yaml += `${prefix}${safeKey}:\n`
96
+ yaml += convertToYaml(value, indent + 4)
97
+ } else {
98
+ yaml += `${prefix}${safeKey}: ${formatYamlValue(value)}\n`
94
99
  }
95
- }
100
+ })
96
101
  } else {
97
102
  yaml += `${spaces}- ${formatYamlValue(item)}\n`
98
103
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-qa-architect",
3
- "version": "5.0.1",
3
+ "version": "5.0.6",
4
4
  "description": "QA Architect - Bootstrap quality automation for JavaScript/TypeScript and Python projects with GitHub Actions, pre-commit hooks, linting, formatting, and smart test strategy",
5
5
  "main": "setup.js",
6
6
  "bin": {
@@ -12,17 +12,17 @@
12
12
  "format": "prettier --write .",
13
13
  "format:check": "prettier --check .",
14
14
  "lint": "eslint . && stylelint \"**/*.{css,scss,sass,less,pcss}\" --allow-empty-input",
15
+ "type-check": "tsc --noEmit",
15
16
  "lint:fix": "eslint . --fix && stylelint \"**/*.{css,scss,sass,less,pcss}\" --fix --allow-empty-input",
16
17
  "security:audit": "npm audit --audit-level high",
17
18
  "security:secrets": "node -e \"const fs=require('fs');const content=fs.readFileSync('package.json','utf8');if(/[\\\"\\'][a-zA-Z0-9+/]{20,}[\\\"\\']/.test(content)){console.error('โŒ Potential hardcoded secrets in package.json');process.exit(1)}else{console.log('โœ… No secrets detected in package.json')}\"",
18
19
  "security:config": "node setup.js --security-config",
19
20
  "validate:docs": "node setup.js --validate-docs",
20
- "validate:claude": "node scripts/validate-claude-md.js",
21
21
  "validate:comprehensive": "node setup.js --comprehensive --no-markdownlint",
22
- "validate:all": "npm run validate:comprehensive && npm run security:audit && npm run validate:claude",
22
+ "validate:all": "npm run validate:comprehensive && npm run security:audit",
23
23
  "validate:pre-push": "npm run test:patterns --if-present && npm run lint && npm run format:check && npm run test:commands --if-present && npm test --if-present",
24
- "test": "export QAA_DEVELOPER=true && node tests/setup.test.js && node tests/integration.test.js && node tests/error-paths.test.js && node tests/error-messages.test.js && node tests/cache-manager.test.js && node tests/parallel-validation.test.js && node tests/python-integration.test.js && node tests/interactive.test.js && node tests/monorepo.test.js && node tests/template-loader.test.js && node tests/critical-fixes.test.js && node tests/interactive-routing-fix.test.js && node tests/telemetry.test.js && node tests/error-reporter.test.js && node tests/premium-dependency-monitoring.test.js && node tests/multi-language-dependency-monitoring.test.js && node tests/cli-deps-integration.test.js && node tests/real-world-packages.test.js && node tests/validation-factory.test.js && node tests/setup-error-coverage.test.js && node tests/python-detection-sensitivity.test.js && node tests/python-parser-fixes.test.js && node tests/licensing.test.js && node tests/security-licensing.test.js && node tests/real-purchase-flow.test.js && node tests/base-validator.test.js && node tests/dependency-monitoring-basic.test.js && node tests/workflow-validation.test.js && node tests/setup-critical-paths.test.js && node tests/project-maturity.test.js && node tests/project-maturity-cli.test.js && node tests/package-manager-detection.test.js && node tests/check-docs.test.js && node tests/validate-claude-md.test.js && node tests/validate-command-patterns.test.js && node tests/gitleaks-binary-resolution.test.js && node tests/gitleaks-production-checksums.test.js && node tests/gitleaks-checksum-verification.test.js && node tests/gitleaks-real-binary-test.js && node tests/tier-enforcement.test.js",
25
- "test:unit": "export QAA_DEVELOPER=true && node tests/setup.test.js && node tests/error-paths.test.js && node tests/error-messages.test.js && node tests/cache-manager.test.js && node tests/template-loader.test.js && node tests/telemetry.test.js && node tests/error-reporter.test.js && node tests/validation-factory.test.js && node tests/setup-error-coverage.test.js && node tests/licensing.test.js && node tests/security-licensing.test.js && node tests/base-validator.test.js && node tests/dependency-monitoring-basic.test.js && node tests/workflow-validation.test.js && node tests/setup-critical-paths.test.js && node tests/project-maturity.test.js && node tests/package-manager-detection.test.js && node tests/check-docs.test.js && node tests/validate-claude-md.test.js && node tests/validate-command-patterns.test.js && node tests/gitleaks-binary-resolution.test.js && node tests/gitleaks-production-checksums.test.js && node tests/gitleaks-checksum-verification.test.js",
24
+ "test": "export QAA_DEVELOPER=true && node tests/setup.test.js && node tests/integration.test.js && node tests/error-paths.test.js && node tests/error-messages.test.js && node tests/cache-manager.test.js && node tests/parallel-validation.test.js && node tests/python-integration.test.js && node tests/interactive.test.js && node tests/monorepo.test.js && node tests/template-loader.test.js && node tests/critical-fixes.test.js && node tests/interactive-routing-fix.test.js && node tests/telemetry.test.js && node tests/error-reporter.test.js && node tests/premium-dependency-monitoring.test.js && node tests/multi-language-dependency-monitoring.test.js && node tests/cli-deps-integration.test.js && node tests/real-world-packages.test.js && node tests/validation-factory.test.js && node tests/setup-error-coverage.test.js && node tests/python-detection-sensitivity.test.js && node tests/python-parser-fixes.test.js && node tests/licensing.test.js && node tests/security-licensing.test.js && node tests/real-purchase-flow.test.js && node tests/base-validator.test.js && node tests/dependency-monitoring-basic.test.js && node tests/workflow-validation.test.js && node tests/setup-critical-paths.test.js && node tests/project-maturity.test.js && node tests/project-maturity-cli.test.js && node tests/package-manager-detection.test.js && node tests/check-docs.test.js && node tests/validate-command-patterns.test.js && node tests/gitleaks-binary-resolution.test.js && node tests/gitleaks-production-checksums.test.js && node tests/gitleaks-checksum-verification.test.js && node tests/gitleaks-real-binary-test.js && node tests/tier-enforcement.test.js",
25
+ "test:unit": "export QAA_DEVELOPER=true && node tests/setup.test.js && node tests/error-paths.test.js && node tests/error-messages.test.js && node tests/cache-manager.test.js && node tests/template-loader.test.js && node tests/telemetry.test.js && node tests/error-reporter.test.js && node tests/validation-factory.test.js && node tests/setup-error-coverage.test.js && node tests/licensing.test.js && node tests/security-licensing.test.js && node tests/base-validator.test.js && node tests/dependency-monitoring-basic.test.js && node tests/workflow-validation.test.js && node tests/setup-critical-paths.test.js && node tests/project-maturity.test.js && node tests/package-manager-detection.test.js && node tests/check-docs.test.js && node tests/validate-command-patterns.test.js && node tests/gitleaks-binary-resolution.test.js && node tests/gitleaks-production-checksums.test.js && node tests/gitleaks-checksum-verification.test.js",
26
26
  "test:fast": "npm run test:unit",
27
27
  "test:medium": "npm run test:fast && npm run test:patterns && npm run test:commands",
28
28
  "test:slow": "export QAA_DEVELOPER=true && node tests/python-integration.test.js && node tests/interactive.test.js && node tests/monorepo.test.js && node tests/critical-fixes.test.js && node tests/interactive-routing-fix.test.js && node tests/premium-dependency-monitoring.test.js && node tests/multi-language-dependency-monitoring.test.js && node tests/cli-deps-integration.test.js && node tests/real-world-packages.test.js && node tests/python-detection-sensitivity.test.js && node tests/python-parser-fixes.test.js && node tests/real-purchase-flow.test.js && node tests/project-maturity-cli.test.js && node tests/gitleaks-real-binary-test.js && npm run test:e2e",
@@ -73,6 +73,8 @@
73
73
  "legal/",
74
74
  "marketing/",
75
75
  "templates/",
76
+ "scripts/",
77
+ "LICENSE",
76
78
  ".github/",
77
79
  ".prettierrc",
78
80
  ".prettierignore",
@@ -84,12 +86,12 @@
84
86
  ],
85
87
  "repository": {
86
88
  "type": "git",
87
- "url": "git+https://github.com/brettstark73/qa-architect.git"
89
+ "url": "git+https://github.com/vibebuildlab/qa-architect.git"
88
90
  },
89
91
  "bugs": {
90
- "url": "https://github.com/brettstark73/qa-architect/issues"
92
+ "url": "https://github.com/vibebuildlab/qa-architect/issues"
91
93
  },
92
- "homepage": "https://github.com/brettstark73/qa-architect#readme",
94
+ "homepage": "https://vibebuildlab.com/tools/qa-architect",
93
95
  "engines": {
94
96
  "node": ">=20"
95
97
  },
@@ -104,7 +106,9 @@
104
106
  }
105
107
  },
106
108
  "devDependencies": {
109
+ "@types/node": "^20",
107
110
  "actionlint": "^2.0.6",
111
+ "typescript": "^5",
108
112
  "c8": "^10.1.2",
109
113
  "eslint": "^9.12.0",
110
114
  "eslint-plugin-security": "^3.0.1",
@@ -121,7 +125,6 @@
121
125
  },
122
126
  "lint-staged": {
123
127
  "CLAUDE.md": [
124
- "node scripts/validate-claude-md.js",
125
128
  "prettier --write"
126
129
  ],
127
130
  "config/defaults.js": [
@@ -0,0 +1,63 @@
1
+ #!/bin/bash
2
+ # Documentation consistency checker
3
+ # Run before any release to catch documentation gaps
4
+
5
+ set -e
6
+
7
+ echo "๐Ÿ” Checking documentation consistency..."
8
+
9
+ # Check version consistency
10
+ PACKAGE_VERSION=$(node -p "require('./package.json').version")
11
+ if ! grep -q "## \[$PACKAGE_VERSION\]" CHANGELOG.md; then
12
+ echo "โŒ CHANGELOG.md missing entry for version $PACKAGE_VERSION"
13
+ exit 1
14
+ fi
15
+
16
+ # Check that setup.js file creation matches README documentation
17
+ echo "๐Ÿ“ Verifying file inventory..."
18
+
19
+ # Extract files created by setup.js
20
+ SETUP_FILES=$(grep -E "writeFileSync.*Path" setup.js | sed -E 's/.*writeFileSync\([^,]+, [^)]+\)//' | wc -l)
21
+ echo "Setup script creates approximately $SETUP_FILES files"
22
+
23
+ # Check for common missing files in README
24
+ MISSING_FILES=()
25
+
26
+ if grep -q "\.nvmrc" setup.js && ! grep -q "\.nvmrc" README.md; then
27
+ MISSING_FILES+=(".nvmrc")
28
+ fi
29
+
30
+ if grep -q "\.npmrc" setup.js && ! grep -q "\.npmrc" README.md; then
31
+ MISSING_FILES+=(".npmrc")
32
+ fi
33
+
34
+ if grep -q "stylelintrc" setup.js && ! grep -q "stylelintrc" README.md; then
35
+ MISSING_FILES+=(".stylelintrc.json")
36
+ fi
37
+
38
+ if grep -q "lighthouserc" setup.js && ! grep -q "lighthouserc" README.md; then
39
+ MISSING_FILES+=(".lighthouserc.js")
40
+ fi
41
+
42
+ if [ ${#MISSING_FILES[@]} -gt 0 ]; then
43
+ echo "โŒ README.md missing documentation for files:"
44
+ printf ' - %s\n' "${MISSING_FILES[@]}"
45
+ exit 1
46
+ fi
47
+
48
+ # Check for Python features if implemented
49
+ if grep -q "Python" setup.js; then
50
+ if ! grep -q "Python" README.md; then
51
+ echo "โŒ Python features implemented but not documented in README.md"
52
+ exit 1
53
+ fi
54
+ fi
55
+
56
+ # Security validation is now handled by:
57
+ # - /bs:audit --security command
58
+ # - security-auditor agent
59
+ # - npm audit in CI workflows
60
+ # - gitleaks in pre-push hooks
61
+ echo "๐Ÿ” Security validation handled by automated tooling (npm audit, gitleaks, CI workflows)"
62
+
63
+ echo "โœ… Documentation consistency checks passed!"
@@ -0,0 +1,98 @@
1
+ #!/bin/bash
2
+ # Smart Test Strategy - QA Architect
3
+ set -e
4
+
5
+ echo "๐Ÿง  Analyzing changes for optimal test strategy..."
6
+
7
+ # =============================================================================
8
+ # SECURITY: Always run npm audit for critical vulnerabilities (fast, ~2 seconds)
9
+ # =============================================================================
10
+ echo ""
11
+ echo "๐Ÿ”’ Running security audit (critical vulnerabilities only)..."
12
+ if npm audit --audit-level=critical --omit=dev 2>/dev/null; then
13
+ echo "โœ… No critical vulnerabilities found"
14
+ else
15
+ echo "โŒ CRITICAL vulnerabilities detected! Fix before pushing."
16
+ echo " Run: npm audit fix"
17
+ exit 1
18
+ fi
19
+ echo ""
20
+
21
+ # Collect metrics
22
+ CHANGED_FILES=$(git diff --name-only HEAD~1..HEAD 2>/dev/null | wc -l | tr -d ' ')
23
+ CHANGED_LINES=$(git diff --stat HEAD~1..HEAD 2>/dev/null | tail -1 | grep -o '[0-9]* insertions' | grep -o '[0-9]*' || echo "0")
24
+ CURRENT_BRANCH=$(git branch --show-current)
25
+ HOUR=$(date +%H)
26
+ DAY_OF_WEEK=$(date +%u)
27
+
28
+ # Project-specific high-risk patterns
29
+ HIGH_RISK_FILES=$(git diff --name-only HEAD~1..HEAD 2>/dev/null | grep -E "(setup\.js|lib/.*|templates/.*|config/.*)" || true)
30
+ API_FILES=$(git diff --name-only HEAD~1..HEAD 2>/dev/null | grep -E "api/" || true)
31
+ CONFIG_FILES=$(git diff --name-only HEAD~1..HEAD 2>/dev/null | grep -E "(package\.json|\.env|config)" || true)
32
+ TEST_FILES=$(git diff --name-only HEAD~1..HEAD 2>/dev/null | grep -E "test|spec" || true)
33
+
34
+ # Calculate risk score (0-10)
35
+ RISK_SCORE=0
36
+
37
+ # File-based risk
38
+ [[ -n "$HIGH_RISK_FILES" ]] && RISK_SCORE=$((RISK_SCORE + 4))
39
+ [[ -n "$API_FILES" ]] && RISK_SCORE=$((RISK_SCORE + 2))
40
+ [[ -n "$CONFIG_FILES" ]] && RISK_SCORE=$((RISK_SCORE + 2))
41
+
42
+ # Size-based risk
43
+ [[ $CHANGED_FILES -gt 10 ]] && RISK_SCORE=$((RISK_SCORE + 2))
44
+ [[ $CHANGED_FILES -gt 20 ]] && RISK_SCORE=$((RISK_SCORE + 3))
45
+ [[ $CHANGED_LINES -gt 200 ]] && RISK_SCORE=$((RISK_SCORE + 2))
46
+
47
+ # Branch-based risk
48
+ case $CURRENT_BRANCH in
49
+ main|master|production) RISK_SCORE=$((RISK_SCORE + 3)) ;;
50
+ hotfix/*) RISK_SCORE=$((RISK_SCORE + 4)) ;;
51
+ release/*) RISK_SCORE=$((RISK_SCORE + 2)) ;;
52
+ develop) RISK_SCORE=$((RISK_SCORE + 1)) ;;
53
+ esac
54
+
55
+ # Time pressure adjustment (strip leading zeros)
56
+ HOUR_NUM=$((10#$HOUR))
57
+ if [[ $HOUR_NUM -ge 9 && $HOUR_NUM -le 17 && $DAY_OF_WEEK -le 5 ]]; then
58
+ SPEED_BONUS=true
59
+ else
60
+ SPEED_BONUS=false
61
+ fi
62
+
63
+ # Display analysis
64
+ echo "๐Ÿ“Š Analysis Results:"
65
+ echo " ๐Ÿ“ Files: $CHANGED_FILES"
66
+ echo " ๐Ÿ“ Lines: $CHANGED_LINES"
67
+ echo " ๐ŸŒฟ Branch: $CURRENT_BRANCH"
68
+ echo " ๐ŸŽฏ Risk Score: $RISK_SCORE/10"
69
+ echo " โšก Speed Bonus: $SPEED_BONUS"
70
+ echo ""
71
+
72
+ # Decision logic
73
+ # NOTE: test:commands and test:e2e are ALWAYS excluded from pre-push (run in CI only)
74
+ # - test:commands: Takes 60+ seconds, verifies npm scripts work in isolated env
75
+ # - test:e2e: Requires browser/package build, CI has better infrastructure
76
+ # These run in GitHub Actions on every PR and push to main
77
+
78
+ if [[ $RISK_SCORE -ge 7 ]]; then
79
+ echo "๐Ÿ”ด HIGH RISK - Comprehensive validation (pre-push)"
80
+ echo " โ€ข Patterns + unit tests + security audit"
81
+ echo " โ€ข (command + e2e tests run in CI only)"
82
+ npm run test:patterns && npm test && npm run security:audit
83
+ elif [[ $RISK_SCORE -ge 4 ]]; then
84
+ echo "๐ŸŸก MEDIUM RISK - Standard validation"
85
+ echo " โ€ข Fast tests + patterns"
86
+ npm run test:patterns && npm run test:fast
87
+ elif [[ $RISK_SCORE -ge 2 || "$SPEED_BONUS" == "false" ]]; then
88
+ echo "๐ŸŸข LOW RISK - Fast validation"
89
+ echo " โ€ข Unit tests only"
90
+ npm run test:fast
91
+ else
92
+ echo "โšช MINIMAL RISK - Quality checks only"
93
+ echo " โ€ข Lint + format check"
94
+ npm run lint && npm run format:check
95
+ fi
96
+
97
+ echo ""
98
+ echo "๐Ÿ’ก Tip: Run 'npm run test:comprehensive' locally for full validation"
@@ -0,0 +1,283 @@
1
+ #!/bin/bash
2
+ # E2E Package Test - Validates the package works for consumers
3
+ # Catches issues like Codex findings before release
4
+
5
+ set -e
6
+
7
+ # Use isolated npm cache to avoid permission issues on shared caches
8
+ export npm_config_cache="${npm_config_cache:-$(mktemp -d)}"
9
+ export NPM_CONFIG_CACHE="$npm_config_cache"
10
+ # Disable husky during packaging so pack works in CI/sandboxed environments
11
+ export HUSKY=0
12
+
13
+ echo "๐Ÿงช E2E Package Validation Test"
14
+ echo "================================"
15
+ echo ""
16
+
17
+ # Colors
18
+ RED='\033[0;31m'
19
+ GREEN='\033[0;32m'
20
+ YELLOW='\033[1;33m'
21
+ NC='\033[0m' # No Color
22
+
23
+ # Track failures
24
+ FAILURES=0
25
+
26
+ fail() {
27
+ echo -e "${RED}โŒ $1${NC}"
28
+ FAILURES=$((FAILURES + 1))
29
+ }
30
+
31
+ pass() {
32
+ echo -e "${GREEN}โœ… $1${NC}"
33
+ }
34
+
35
+ warn() {
36
+ echo -e "${YELLOW}โš ๏ธ $1${NC}"
37
+ }
38
+
39
+ # 1. Package Contents Validation
40
+ echo "๐Ÿ“ฆ Step 1: Validating package contents..."
41
+ echo "Running: npm pack (scripts disabled)"
42
+ TARBALL=$(npm pack --ignore-scripts 2>&1 | tail -1)
43
+
44
+ if [ ! -f "$TARBALL" ]; then
45
+ fail "npm pack failed to create tarball"
46
+ exit 1
47
+ fi
48
+
49
+ pass "Created tarball: $TARBALL"
50
+
51
+ # Extract tarball and check files
52
+ EXTRACT_DIR=$(mktemp -d)
53
+ tar -xzf "$TARBALL" -C "$EXTRACT_DIR"
54
+ PKG_DIR="$EXTRACT_DIR/package"
55
+
56
+ echo " Checking required files in package..."
57
+ REQUIRED_FILES=(
58
+ "setup.js"
59
+ ".prettierrc"
60
+ ".prettierignore"
61
+ "eslint.config.cjs"
62
+ "eslint.config.ts.cjs"
63
+ ".stylelintrc.json"
64
+ ".editorconfig"
65
+ ".nvmrc"
66
+ "config/defaults.js"
67
+ "lib/validation/index.js"
68
+ ".github/workflows/quality.yml"
69
+ )
70
+ # Note: .npmrc is intentionally excluded - npm won't package it anyway (local config only)
71
+
72
+ for file in "${REQUIRED_FILES[@]}"; do
73
+ if [ -f "$PKG_DIR/$file" ] || [ -d "$PKG_DIR/$file" ]; then
74
+ pass " $file"
75
+ else
76
+ fail " Missing required file: $file"
77
+ fi
78
+ done
79
+
80
+ # 2. Consumer Installation Simulation
81
+ echo ""
82
+ echo "๐Ÿ—๏ธ Step 2: Simulating consumer installation..."
83
+ TEST_DIR=$(mktemp -d)
84
+ cd "$TEST_DIR"
85
+
86
+ echo " Creating test project..."
87
+ git init -q
88
+ git config user.email "test@example.com"
89
+ git config user.name "Test User"
90
+
91
+ cat > package.json <<'EOF'
92
+ {
93
+ "name": "e2e-test-consumer",
94
+ "version": "1.0.0",
95
+ "description": "E2E test consumer",
96
+ "keywords": ["test"],
97
+ "license": "MIT"
98
+ }
99
+ EOF
100
+
101
+ pass "Test project created"
102
+
103
+ echo " Installing from tarball..."
104
+ npm install "$OLDPWD/$TARBALL" --silent 2>&1 > /dev/null || {
105
+ fail "npm install from tarball failed"
106
+ cd "$OLDPWD"
107
+ rm -rf "$TEST_DIR" "$EXTRACT_DIR"
108
+ rm -f "$TARBALL"
109
+ exit 1
110
+ }
111
+
112
+ pass "Package installed"
113
+
114
+ # 3. Run setup
115
+ echo ""
116
+ echo "๐Ÿš€ Step 3: Running setup..."
117
+ SETUP_OUTPUT=$(QAA_DEVELOPER=true node ./node_modules/create-qa-architect/setup.js 2>&1)
118
+ echo "$SETUP_OUTPUT" | grep -q "Setting up Quality Automation" && pass "Setup executed" || fail "Setup failed"
119
+ echo " Setup output:"
120
+ echo "$SETUP_OUTPUT" | head -20
121
+
122
+ # 4. Verify generated files
123
+ echo ""
124
+ echo "๐Ÿ“‹ Step 4: Verifying generated files..."
125
+ EXPECTED_FILES=(
126
+ ".prettierrc"
127
+ ".prettierignore"
128
+ "eslint.config.cjs"
129
+ ".stylelintrc.json"
130
+ ".editorconfig"
131
+ ".nvmrc"
132
+ ".npmrc"
133
+ ".github/workflows/quality.yml"
134
+ )
135
+
136
+ for file in "${EXPECTED_FILES[@]}"; do
137
+ if [ -f "$file" ]; then
138
+ pass " Generated: $file"
139
+ else
140
+ fail " Missing generated file: $file"
141
+ fi
142
+ done
143
+
144
+ # 5. Validate package.json modifications
145
+ echo ""
146
+ echo "๐Ÿ“ Step 5: Validating package.json modifications..."
147
+
148
+ if grep -q "\"format\":" package.json; then
149
+ pass " npm scripts added"
150
+ else
151
+ fail " npm scripts not added"
152
+ fi
153
+
154
+ if grep -q "husky" package.json; then
155
+ pass " devDependencies added"
156
+ else
157
+ fail " devDependencies not added"
158
+ fi
159
+
160
+ if grep -q "lint-staged" package.json; then
161
+ pass " lint-staged config added"
162
+ else
163
+ fail " lint-staged config not added"
164
+ fi
165
+
166
+ # 6. Test npm scripts use npx (not node setup.js)
167
+ echo ""
168
+ echo "๐Ÿ” Step 6: Validating npm scripts use npx..."
169
+
170
+ if grep -q "\"security:config.*npx create-qa-architect" package.json; then
171
+ pass " security:config uses npx"
172
+ else
173
+ fail " security:config doesn't use npx (Codex finding regression!)"
174
+ fi
175
+
176
+ if grep -q "\"validate:docs.*npx create-qa-architect" package.json; then
177
+ pass " validate:docs uses npx"
178
+ else
179
+ fail " validate:docs doesn't use npx (Codex finding regression!)"
180
+ fi
181
+
182
+ # 7. Validate workflow doesn't have UNCONDITIONAL setup.js references
183
+ echo ""
184
+ echo "๐Ÿ”ง Step 7: Validating generated workflow..."
185
+
186
+ # The workflow can have conditional references like:
187
+ # if [ -f "setup.js" ]; then
188
+ # node setup.js --something
189
+ # fi
190
+ # But should NOT have unconditional references like the old:
191
+ # node "$GITHUB_WORKSPACE/setup.js"
192
+ #
193
+ # Check for the specific bad pattern we fixed (Codex finding)
194
+ if grep -q 'node "$GITHUB_WORKSPACE/setup.js"' .github/workflows/quality.yml; then
195
+ fail " Workflow has unconditional GITHUB_WORKSPACE setup.js reference (Codex finding regression!)"
196
+ else
197
+ pass " Workflow doesn't have unconditional setup.js references"
198
+ fi
199
+
200
+ # Conditional references with guards are OK (will fallback in consumer repos)
201
+
202
+ # 8. NEW: Actually run the generated commands (catches broken CLI flags!)
203
+ echo ""
204
+ echo "๐Ÿš€ Step 8: Testing generated commands actually work..."
205
+ echo " This step would have caught the ESLint --ext bug!"
206
+
207
+ # Install devDependencies first
208
+ echo " Installing devDependencies..."
209
+ npm install --silent > /dev/null 2>&1 || {
210
+ fail " npm install failed"
211
+ }
212
+
213
+ # Create test files for commands to process
214
+ # Use valid code that won't trigger linting errors
215
+ echo "module.exports = { name: 'test' };" > test.js
216
+ echo "body { color: red; }" > test.css
217
+
218
+ # Test format:check - should work (even if files need formatting)
219
+ echo " Testing: npm run format:check"
220
+ # Format the files first so format:check passes
221
+ npm run format >/dev/null 2>&1
222
+ if npm run format:check 2>&1 >/dev/null; then
223
+ pass " format:check works"
224
+ else
225
+ fail " format:check failed (check Prettier flags!)"
226
+ fi
227
+
228
+ # Test lint (CRITICAL: this would have caught --ext bug!)
229
+ echo " Testing: npm run lint"
230
+ LINT_OUTPUT=$(npm run lint 2>&1)
231
+ if echo "$LINT_OUTPUT" | grep -q "error"; then
232
+ fail " lint failed (check for deprecated flags like --ext!)"
233
+ echo " ESLint error output:"
234
+ echo "$LINT_OUTPUT" | grep -A 5 "error" | head -10
235
+ else
236
+ pass " lint works"
237
+ fi
238
+
239
+ # Test direct ESLint
240
+ echo " Testing: npx eslint test.js"
241
+ if npx eslint test.js 2>&1 >/dev/null; then
242
+ pass " Direct ESLint works"
243
+ else
244
+ fail " Direct ESLint failed"
245
+ fi
246
+
247
+ # Test stylelint
248
+ echo " Testing: npx stylelint test.css"
249
+ if npx stylelint test.css 2>&1 >/dev/null; then
250
+ pass " Stylelint works"
251
+ else
252
+ fail " Stylelint failed"
253
+ fi
254
+
255
+ # 9. Test --dry-run mode
256
+ echo ""
257
+ echo "๐Ÿงช Step 9: Testing --dry-run mode..."
258
+ cd "$OLDPWD"
259
+ if node ./setup.js --dry-run 2>&1 | grep -q "DRY RUN MODE"; then
260
+ pass "--dry-run mode works"
261
+ else
262
+ fail "--dry-run mode doesn't work"
263
+ fi
264
+
265
+ # Cleanup
266
+ cd "$OLDPWD"
267
+ rm -rf "$TEST_DIR" "$EXTRACT_DIR"
268
+ rm -f "$TARBALL"
269
+
270
+ # Report
271
+ echo ""
272
+ echo "================================"
273
+ if [ $FAILURES -eq 0 ]; then
274
+ echo -e "${GREEN}โœ… All E2E tests passed!${NC}"
275
+ echo ""
276
+ echo "Package is ready for release."
277
+ exit 0
278
+ else
279
+ echo -e "${RED}โŒ $FAILURES test(s) failed${NC}"
280
+ echo ""
281
+ echo "Fix these issues before releasing."
282
+ exit 1
283
+ fi