create-qa-architect 5.12.1 → 5.13.3

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.
Files changed (38) hide show
  1. package/.github/dependabot.yml +10 -30
  2. package/.github/workflows/claude-md-validation.yml +5 -7
  3. package/.github/workflows/dependabot-auto-merge.yml +1 -0
  4. package/.github/workflows/quality.yml +26 -12
  5. package/.github/workflows/release.yml +2 -1
  6. package/.github/workflows/stale-prs.yml +42 -0
  7. package/.github/workflows/weekly-gitleaks-verification.yml +6 -4
  8. package/LICENSE +5 -5
  9. package/README.md +22 -21
  10. package/config/defaults.js +2 -3
  11. package/config/quality-config.schema.json +1 -1
  12. package/docs/CI-COST-ANALYSIS.md +8 -8
  13. package/docs/DEPLOYMENT.md +1 -1
  14. package/docs/DEVELOPMENT-WORKFLOW.md +2 -2
  15. package/docs/TURBOREPO-SUPPORT.md +3 -3
  16. package/docs/dev_guide/CONVENTIONS.md +132 -0
  17. package/eslint.config.cjs +25 -0
  18. package/lib/blob-storage.js +57 -0
  19. package/lib/commands/analyze-ci.js +267 -27
  20. package/lib/commands/deps.js +5 -5
  21. package/lib/commands/license-commands.js +2 -2
  22. package/lib/commands/maturity-check.js +20 -2
  23. package/lib/dependency-monitoring-basic.js +4 -4
  24. package/lib/dependency-monitoring-premium.js +5 -5
  25. package/lib/license-validator.js +2 -2
  26. package/lib/licensing.js +7 -9
  27. package/lib/smart-strategy-generator.js +1 -1
  28. package/lib/validation/documentation.js +2 -0
  29. package/lib/workflow-config.js +176 -73
  30. package/package.json +53 -23
  31. package/scripts/deploy-consumers.sh +369 -0
  32. package/scripts/pattern-check.sh +607 -0
  33. package/scripts/run-semgrep.sh +244 -0
  34. package/scripts/smart-test-strategy.sh +1 -1
  35. package/setup.js +119 -71
  36. package/templates/CLAUDE_WORKFLOW_POLICY.md +3 -3
  37. package/templates/scripts/smart-test-strategy.sh +1 -1
  38. package/.github/workflows/auto-release.yml +0 -39
@@ -0,0 +1,244 @@
1
+ #!/bin/bash
2
+ # =============================================================================
3
+ # Run Semgrep - Defensive Pattern Security Scan
4
+ # =============================================================================
5
+ # Runs Semgrep with defensive pattern rules. Falls back to LLM analysis
6
+ # if Semgrep is not installed.
7
+ #
8
+ # Part of CS-090: Semgrep Integration for Patterns
9
+ #
10
+ # USAGE:
11
+ # ./scripts/run-semgrep.sh # Scan current directory
12
+ # ./scripts/run-semgrep.sh --install # Install semgrep
13
+ # ./scripts/run-semgrep.sh --ci # CI mode (exit codes)
14
+ # ./scripts/run-semgrep.sh src/ # Scan specific directory
15
+ # =============================================================================
16
+
17
+ set -euo pipefail
18
+
19
+ # Colors
20
+ RED='\033[0;31m'
21
+ GREEN='\033[0;32m'
22
+ YELLOW='\033[1;33m'
23
+ BLUE='\033[0;34m'
24
+ NC='\033[0m'
25
+
26
+ # Configuration
27
+ SEMGREP_CONFIG=".semgrep/defensive-patterns.yaml"
28
+ CI_MODE=false
29
+ INSTALL_MODE=false
30
+ SCAN_DIR="."
31
+ OUTPUT_FORMAT="text"
32
+ OUTPUT_FILE=""
33
+
34
+ # Get script directory
35
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
36
+ PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
37
+
38
+ # Parse arguments
39
+ while [[ $# -gt 0 ]]; do
40
+ case "$1" in
41
+ --install)
42
+ INSTALL_MODE=true
43
+ shift
44
+ ;;
45
+ --ci)
46
+ CI_MODE=true
47
+ OUTPUT_FORMAT="json"
48
+ shift
49
+ ;;
50
+ --json)
51
+ OUTPUT_FORMAT="json"
52
+ shift
53
+ ;;
54
+ --sarif)
55
+ OUTPUT_FORMAT="sarif"
56
+ shift
57
+ ;;
58
+ --output|-o)
59
+ OUTPUT_FILE="$2"
60
+ shift 2
61
+ ;;
62
+ --config|-c)
63
+ SEMGREP_CONFIG="$2"
64
+ shift 2
65
+ ;;
66
+ --help|-h)
67
+ echo "Usage: run-semgrep.sh [OPTIONS] [DIRECTORY]"
68
+ echo ""
69
+ echo "Options:"
70
+ echo " --install Install semgrep via pip"
71
+ echo " --ci CI mode (json output, proper exit codes)"
72
+ echo " --json Output as JSON"
73
+ echo " --sarif Output as SARIF (for GitHub Security)"
74
+ echo " --output Write output to file"
75
+ echo " --config Custom semgrep config (default: .semgrep/defensive-patterns.yaml)"
76
+ echo " --help Show this help message"
77
+ echo ""
78
+ echo "Examples:"
79
+ echo " run-semgrep.sh # Scan current dir"
80
+ echo " run-semgrep.sh --install # Install semgrep"
81
+ echo " run-semgrep.sh --ci --output report.json"
82
+ exit 0
83
+ ;;
84
+ -*)
85
+ echo -e "${RED}Unknown option: $1${NC}"
86
+ exit 1
87
+ ;;
88
+ *)
89
+ SCAN_DIR="$1"
90
+ shift
91
+ ;;
92
+ esac
93
+ done
94
+
95
+ # Install semgrep if requested
96
+ if [[ "$INSTALL_MODE" == "true" ]]; then
97
+ echo -e "${BLUE}Installing Semgrep...${NC}"
98
+
99
+ if command -v pip3 &> /dev/null; then
100
+ pip3 install semgrep
101
+ elif command -v pip &> /dev/null; then
102
+ pip install semgrep
103
+ elif command -v brew &> /dev/null; then
104
+ brew install semgrep
105
+ else
106
+ echo -e "${RED}Error: No package manager found (pip3, pip, or brew)${NC}"
107
+ echo "Install manually: https://semgrep.dev/docs/getting-started/"
108
+ exit 1
109
+ fi
110
+
111
+ echo -e "${GREEN}✓ Semgrep installed${NC}"
112
+ exit 0
113
+ fi
114
+
115
+ # Check if semgrep is installed
116
+ check_semgrep() {
117
+ if ! command -v semgrep &> /dev/null; then
118
+ return 1
119
+ fi
120
+ return 0
121
+ }
122
+
123
+ # Find the config file
124
+ find_config() {
125
+ # Check local project first
126
+ if [[ -f "$SEMGREP_CONFIG" ]]; then
127
+ echo "$SEMGREP_CONFIG"
128
+ return 0
129
+ fi
130
+
131
+ # Check claude-setup
132
+ local setup_config="$PROJECT_ROOT/.semgrep/defensive-patterns.yaml"
133
+ if [[ -f "$setup_config" ]]; then
134
+ echo "$setup_config"
135
+ return 0
136
+ fi
137
+
138
+ # Check home directory
139
+ local home_config="$HOME/.claude/.semgrep/defensive-patterns.yaml"
140
+ if [[ -f "$home_config" ]]; then
141
+ echo "$home_config"
142
+ return 0
143
+ fi
144
+
145
+ return 1
146
+ }
147
+
148
+ # Run semgrep scan
149
+ run_semgrep() {
150
+ local config_path="$1"
151
+ local scan_path="$2"
152
+
153
+ echo -e "${BLUE}🔍 Running Semgrep Security Scan${NC}"
154
+ echo "═══════════════════════════════════════════════════════════"
155
+ echo ""
156
+ echo "Config: $config_path"
157
+ echo "Scanning: $scan_path"
158
+ echo ""
159
+
160
+ local semgrep_args=(
161
+ "--config" "$config_path"
162
+ "--exclude" "node_modules"
163
+ "--exclude" "dist"
164
+ "--exclude" "build"
165
+ "--exclude" ".next"
166
+ "--exclude" "coverage"
167
+ "--exclude" "*.min.js"
168
+ "--exclude" "*.bundle.js"
169
+ )
170
+
171
+ # Add output format
172
+ case "$OUTPUT_FORMAT" in
173
+ json)
174
+ semgrep_args+=("--json")
175
+ ;;
176
+ sarif)
177
+ semgrep_args+=("--sarif")
178
+ ;;
179
+ esac
180
+
181
+ # Add output file
182
+ if [[ -n "$OUTPUT_FILE" ]]; then
183
+ semgrep_args+=("--output" "$OUTPUT_FILE")
184
+ fi
185
+
186
+ # Run semgrep
187
+ local exit_code=0
188
+ semgrep "${semgrep_args[@]}" "$scan_path" || exit_code=$?
189
+
190
+ echo ""
191
+
192
+ if [[ $exit_code -eq 0 ]]; then
193
+ echo -e "${GREEN}✅ No security issues found${NC}"
194
+ elif [[ $exit_code -eq 1 ]]; then
195
+ echo -e "${YELLOW}⚠️ Security findings detected${NC}"
196
+ if [[ "$CI_MODE" == "true" ]]; then
197
+ echo "Review findings above and fix before merging."
198
+ fi
199
+ else
200
+ echo -e "${RED}❌ Semgrep scan failed (exit code: $exit_code)${NC}"
201
+ fi
202
+
203
+ return $exit_code
204
+ }
205
+
206
+ # Fallback LLM analysis when semgrep not available
207
+ fallback_llm_analysis() {
208
+ echo -e "${YELLOW}⚠️ Semgrep not installed - using LLM-based analysis${NC}"
209
+ echo ""
210
+ echo "For faster, more reliable scans, install Semgrep:"
211
+ echo " ./scripts/run-semgrep.sh --install"
212
+ echo ""
213
+ echo "Falling back to pattern-check.sh..."
214
+ echo ""
215
+
216
+ # Run the grep-based pattern checker
217
+ if [[ -f "$SCRIPT_DIR/pattern-check.sh" ]]; then
218
+ bash "$SCRIPT_DIR/pattern-check.sh" --all
219
+ return $?
220
+ else
221
+ echo -e "${RED}Error: pattern-check.sh not found${NC}"
222
+ return 1
223
+ fi
224
+ }
225
+
226
+ # Main
227
+ main() {
228
+ if ! check_semgrep; then
229
+ fallback_llm_analysis
230
+ return $?
231
+ fi
232
+
233
+ local config_path
234
+ if ! config_path=$(find_config); then
235
+ echo -e "${RED}Error: Semgrep config not found at $SEMGREP_CONFIG${NC}"
236
+ echo ""
237
+ echo "Create .semgrep/defensive-patterns.yaml or specify with --config"
238
+ exit 1
239
+ fi
240
+
241
+ run_semgrep "$config_path" "$SCAN_DIR"
242
+ }
243
+
244
+ main
@@ -1,7 +1,7 @@
1
1
  #!/bin/bash
2
2
  # Smart Test Strategy - create-qa-architect
3
3
  # Generated by create-qa-architect (Pro/Team/Enterprise feature)
4
- # https://vibebuildlab.com/qa-architect
4
+ # https://buildproven.ai/qa-architect
5
5
  set -e
6
6
 
7
7
  echo "🧠 Analyzing changes for optimal test strategy..."
package/setup.js CHANGED
@@ -125,6 +125,7 @@ const { runInteractiveFlow } = require('./lib/interactive/questions')
125
125
  const { TemplateLoader } = require('./lib/template-loader')
126
126
  const {
127
127
  detectExistingWorkflowMode,
128
+ detectExistingMatrix,
128
129
  injectWorkflowMode,
129
130
  injectMatrix,
130
131
  } = require('./lib/workflow-config')
@@ -693,7 +694,7 @@ Usage: npx create-qa-architect@latest [options]
693
694
  SETUP OPTIONS:
694
695
  (no args) Run complete quality automation setup
695
696
  --interactive Interactive mode with guided configuration prompts
696
- --update Update existing configuration
697
+ --update Update existing configuration (refreshes quality.yml, preserves detected workflow tier)
697
698
  --deps Add basic dependency monitoring (Free Tier)
698
699
  --dependency-monitoring Same as --deps
699
700
  --ci <provider> Select CI provider: github (default) | gitlab | circleci
@@ -701,9 +702,9 @@ SETUP OPTIONS:
701
702
  --dry-run Preview changes without modifying files
702
703
 
703
704
  WORKFLOW TIERS (GitHub Actions optimization):
704
- --workflow-minimal Minimal CI (default) - Single Node version, weekly security
705
- ~5-10 min/commit, ~$0-5/mo for typical projects
706
- --workflow-standard Standard CI - Matrix testing on main, weekly security
705
+ --workflow-minimal Minimal CI (default) - Single Node version, monthly security
706
+ Budget-first mode: detection-only CI (target <1000 min/month)
707
+ --workflow-standard Standard CI - Main-branch tests, monthly security
707
708
  ~15-20 min/commit, ~$5-20/mo for typical projects
708
709
  --workflow-comprehensive Comprehensive CI - Matrix on every push, security inline
709
710
  ~50-100 min/commit, ~$100-350/mo for typical projects
@@ -1161,7 +1162,7 @@ HELP:
1161
1162
  if (!repoCheck.allowed) {
1162
1163
  console.error(`\n❌ ${repoCheck.reason}`)
1163
1164
  console.error(
1164
- ' Upgrade to Pro for unlimited repos: https://vibebuildlab.com/qa-architect'
1165
+ ' Upgrade to Pro for unlimited repos: https://buildproven.ai/qa-architect'
1165
1166
  )
1166
1167
  process.exit(1)
1167
1168
  }
@@ -1531,7 +1532,7 @@ HELP:
1531
1532
  console.error(` • Detected maturity: ${detectedMaturity}`)
1532
1533
  console.error(` • Error count: ${validationResult.errors.length}`)
1533
1534
  console.error(
1534
- ` • https://github.com/vibebuildlab/qa-architect/issues/new\n`
1535
+ ` • https://github.com/buildproven/qa-architect/issues/new\n`
1535
1536
  )
1536
1537
 
1537
1538
  // Don't continue - this is a bug in the tool itself
@@ -1651,6 +1652,16 @@ HELP:
1651
1652
  }
1652
1653
  }
1653
1654
 
1655
+ const hasExplicitWorkflowMode =
1656
+ isWorkflowMinimal || isWorkflowStandard || isWorkflowComprehensive
1657
+ const existingMatrixEnabled =
1658
+ fs.existsSync(workflowFile) &&
1659
+ !isMatrixEnabled &&
1660
+ !hasExplicitWorkflowMode
1661
+ ? detectExistingMatrix(process.cwd())
1662
+ : false
1663
+ const matrixEnabled = isMatrixEnabled || existingMatrixEnabled
1664
+
1654
1665
  if (!fs.existsSync(workflowFile)) {
1655
1666
  let templateWorkflow =
1656
1667
  templateLoader.getTemplate(
@@ -1666,7 +1677,7 @@ HELP:
1666
1677
  templateWorkflow = injectWorkflowMode(templateWorkflow, workflowMode)
1667
1678
 
1668
1679
  // Inject matrix testing if enabled (for library authors)
1669
- templateWorkflow = injectMatrix(templateWorkflow, isMatrixEnabled)
1680
+ templateWorkflow = injectMatrix(templateWorkflow, matrixEnabled)
1670
1681
 
1671
1682
  // Inject collaboration steps
1672
1683
  templateWorkflow = injectCollaborationSteps(templateWorkflow, {
@@ -1677,50 +1688,47 @@ HELP:
1677
1688
  fs.writeFileSync(workflowFile, templateWorkflow)
1678
1689
  console.log(`✅ Added GitHub Actions workflow (${workflowMode} mode)`)
1679
1690
  } else if (isUpdateMode) {
1680
- // Update existing workflow with new mode if explicitly specified
1681
- if (
1682
- isWorkflowMinimal ||
1683
- isWorkflowStandard ||
1684
- isWorkflowComprehensive
1685
- ) {
1686
- // Load fresh template and re-inject
1687
- let templateWorkflow =
1688
- templateLoader.getTemplate(
1689
- templates,
1690
- path.join('.github', 'workflows', 'quality.yml')
1691
- ) ||
1692
- fs.readFileSync(
1693
- path.join(__dirname, '.github/workflows/quality.yml'),
1694
- 'utf8'
1695
- )
1696
-
1697
- // Inject workflow mode configuration
1698
- templateWorkflow = injectWorkflowMode(
1699
- templateWorkflow,
1700
- workflowMode
1691
+ // Refresh existing workflow from the current template.
1692
+ let templateWorkflow =
1693
+ templateLoader.getTemplate(
1694
+ templates,
1695
+ path.join('.github', 'workflows', 'quality.yml')
1696
+ ) ||
1697
+ fs.readFileSync(
1698
+ path.join(__dirname, '.github/workflows/quality.yml'),
1699
+ 'utf8'
1701
1700
  )
1702
1701
 
1703
- // Inject matrix testing if enabled (for library authors)
1704
- templateWorkflow = injectMatrix(templateWorkflow, isMatrixEnabled)
1702
+ // Inject workflow mode configuration
1703
+ templateWorkflow = injectWorkflowMode(templateWorkflow, workflowMode)
1705
1704
 
1706
- // Inject collaboration steps (preserve from existing if present)
1707
- const existingWorkflow = fs.readFileSync(workflowFile, 'utf8')
1708
- const hasSlackAlerts =
1709
- existingWorkflow.includes('SLACK_WEBHOOK_URL')
1710
- const hasPrComments = existingWorkflow.includes(
1711
- 'PR_COMMENT_PLACEHOLDER'
1712
- )
1705
+ // Inject matrix testing if enabled (for library authors)
1706
+ templateWorkflow = injectMatrix(templateWorkflow, matrixEnabled)
1713
1707
 
1714
- templateWorkflow = injectCollaborationSteps(templateWorkflow, {
1715
- enableSlackAlerts: hasSlackAlerts,
1716
- enablePrComments: hasPrComments,
1717
- })
1708
+ // Inject collaboration steps (preserve from existing if present)
1709
+ const existingWorkflow = fs.readFileSync(workflowFile, 'utf8')
1710
+ const hasSlackAlerts = existingWorkflow.includes('SLACK_WEBHOOK_URL')
1711
+ const hasPrComments = existingWorkflow.includes(
1712
+ 'PR_COMMENT_PLACEHOLDER'
1713
+ )
1718
1714
 
1719
- fs.writeFileSync(workflowFile, templateWorkflow)
1715
+ templateWorkflow = injectCollaborationSteps(templateWorkflow, {
1716
+ enableSlackAlerts: hasSlackAlerts,
1717
+ enablePrComments: hasPrComments,
1718
+ })
1719
+
1720
+ fs.writeFileSync(workflowFile, templateWorkflow)
1721
+ if (workflowMode === 'minimal') {
1720
1722
  console.log(
1721
- `♻️ Updated GitHub Actions workflow to ${workflowMode} mode`
1723
+ '⚠️ Minimal mode disables tests and security scans in CI (detection-only).'
1724
+ )
1725
+ console.log(
1726
+ ' Use --workflow-standard to re-enable full CI checks.'
1722
1727
  )
1723
1728
  }
1729
+ console.log(
1730
+ `♻️ Updated GitHub Actions workflow to ${workflowMode} mode`
1731
+ )
1724
1732
  }
1725
1733
  }
1726
1734
 
@@ -1910,8 +1918,26 @@ const fs = require('fs')
1910
1918
  const path = require('path')
1911
1919
  const os = require('os')
1912
1920
 
1913
- const licenseDir =
1921
+ function validateLicenseDir(dirPath) {
1922
+ const resolved = path.resolve(dirPath)
1923
+ const home = os.homedir()
1924
+ const tmp = os.tmpdir()
1925
+ const isInHome = resolved.startsWith(home + path.sep) || resolved === home
1926
+ const isInTmp = resolved.startsWith(tmp + path.sep) || resolved === tmp
1927
+
1928
+ if (!isInHome && !isInTmp) {
1929
+ console.warn(
1930
+ '⚠️ QAA_LICENSE_DIR must be within home or temp directory, ignoring: ' + dirPath
1931
+ )
1932
+ return path.join(home, '.create-qa-architect')
1933
+ }
1934
+
1935
+ return resolved
1936
+ }
1937
+
1938
+ const requestedLicenseDir =
1914
1939
  process.env.QAA_LICENSE_DIR || path.join(os.homedir(), '.create-qa-architect')
1940
+ const licenseDir = validateLicenseDir(requestedLicenseDir)
1915
1941
  const licenseFile = path.join(licenseDir, 'license.json')
1916
1942
  const usageFile = path.join(licenseDir, 'usage.json')
1917
1943
  const now = new Date()
@@ -1948,7 +1974,7 @@ try {
1948
1974
  const CAP = 50
1949
1975
  if (usage.prePushRuns >= CAP) {
1950
1976
  console.error('❌ Free tier limit reached: ' + usage.prePushRuns + '/' + CAP + ' pre-push runs this month')
1951
- console.error(' Upgrade to Pro, Team, or Enterprise: https://vibebuildlab.com/qa-architect')
1977
+ console.error(' Upgrade to Pro, Team, or Enterprise: https://buildproven.ai/qa-architect')
1952
1978
  process.exit(1)
1953
1979
  }
1954
1980
 
@@ -2167,32 +2193,6 @@ echo "✅ Pre-push validation passed!"
2167
2193
  : '✅ Added Shell CI GitHub Actions workflow'
2168
2194
  )
2169
2195
  }
2170
-
2171
- // Copy/update Shell Quality workflow
2172
- const shellQualityWorkflowFile = path.join(
2173
- githubWorkflowDir,
2174
- 'shell-quality.yml'
2175
- )
2176
- if (!fs.existsSync(shellQualityWorkflowFile) || isUpdateMode) {
2177
- const templateShellQualityWorkflow =
2178
- templateLoader.getTemplate(
2179
- templates,
2180
- path.join('config', 'shell-quality.yml')
2181
- ) ||
2182
- fs.readFileSync(
2183
- path.join(__dirname, 'config/shell-quality.yml'),
2184
- 'utf8'
2185
- )
2186
- fs.writeFileSync(
2187
- shellQualityWorkflowFile,
2188
- templateShellQualityWorkflow
2189
- )
2190
- console.log(
2191
- isUpdateMode
2192
- ? '🔄 Updated Shell Quality GitHub Actions workflow'
2193
- : '✅ Added Shell Quality GitHub Actions workflow'
2194
- )
2195
- }
2196
2196
  }
2197
2197
 
2198
2198
  // Create a basic README if it doesn't exist
@@ -2250,6 +2250,54 @@ Quality checks are automated via GitHub Actions:
2250
2250
  fs.unlinkSync(shellQualityWf)
2251
2251
  staleWorkflows.push('shell-quality.yml')
2252
2252
  }
2253
+ } else {
2254
+ // Consolidate shell CI into a single workflow to avoid duplicate runs.
2255
+ const shellQualityWf = path.join(
2256
+ githubWorkflowDir,
2257
+ 'shell-quality.yml'
2258
+ )
2259
+ if (fs.existsSync(shellQualityWf)) {
2260
+ fs.unlinkSync(shellQualityWf)
2261
+ staleWorkflows.push('shell-quality.yml')
2262
+ }
2263
+ }
2264
+
2265
+ // Remove known duplicate CI workflow names that overlap quality.yml,
2266
+ // but ONLY if they were generated by qa-architect (contain a marker).
2267
+ const duplicateCiWorkflows = [
2268
+ 'ci.yml',
2269
+ 'ci.yaml',
2270
+ 'test.yml',
2271
+ 'test.yaml',
2272
+ 'tests.yml',
2273
+ 'tests.yaml',
2274
+ 'quality-legacy.yml',
2275
+ 'quality-legacy.yaml',
2276
+ ]
2277
+ const skippedWorkflows = []
2278
+ for (const duplicateName of duplicateCiWorkflows) {
2279
+ const duplicatePath = path.join(githubWorkflowDir, duplicateName)
2280
+ if (fs.existsSync(duplicatePath)) {
2281
+ const content = fs.readFileSync(duplicatePath, 'utf8')
2282
+ const isQaaGenerated =
2283
+ content.includes('create-qa-architect') ||
2284
+ content.includes('qa-architect') ||
2285
+ content.includes('WORKFLOW_MODE:')
2286
+ if (isQaaGenerated) {
2287
+ fs.unlinkSync(duplicatePath)
2288
+ staleWorkflows.push(duplicateName)
2289
+ } else {
2290
+ skippedWorkflows.push(duplicateName)
2291
+ }
2292
+ }
2293
+ }
2294
+ if (skippedWorkflows.length > 0) {
2295
+ console.log(
2296
+ `⚠️ Found potential duplicate workflows: ${skippedWorkflows.join(', ')}`
2297
+ )
2298
+ console.log(
2299
+ ' These were not created by qa-architect — review manually and remove if redundant with quality.yml'
2300
+ )
2253
2301
  }
2254
2302
  if (staleWorkflows.length > 0) {
2255
2303
  console.log(
@@ -2,7 +2,7 @@
2
2
 
3
3
  ## ⚠️ CRITICAL: Do Not Create Additional Workflows
4
4
 
5
- This project uses **qa-architect** for quality automation with **minimal workflow mode** (~$0-5/mo).
5
+ This project uses **qa-architect** for quality automation with **minimal workflow mode** (budget-first: <1000 min/month target).
6
6
 
7
7
  ### What This Means for AI Assistants (Claude, Copilot, etc.)
8
8
 
@@ -25,13 +25,13 @@ This project uses **qa-architect** for quality automation with **minimal workflo
25
25
 
26
26
  - **Mode:** Minimal (~$0-5/mo per project)
27
27
  - **Path filters:** Skip docs/config changes (60% fewer runs)
28
- - **Security:** Weekly schedule (not every commit)
28
+ - **Security:** Monthly schedule (not every commit)
29
29
  - **Node version:** Single version (22)
30
30
 
31
31
  ### Why This Matters
32
32
 
33
33
  - **Cost control:** Prevents $20-350/mo per-project bloat
34
- - **Efficiency:** Path filters + weekly security = 60-90% CI savings
34
+ - **Efficiency:** Path filters + monthly security = 60-90% CI savings
35
35
  - **Standards:** Consistent automation across all projects
36
36
 
37
37
  ### Upgrading CI (User Decision Only)
@@ -1,7 +1,7 @@
1
1
  #!/bin/bash
2
2
  # Smart Test Strategy - {{PROJECT_NAME}}
3
3
  # Generated by create-qa-architect (Pro/Team/Enterprise feature)
4
- # https://vibebuildlab.com/qa-architect
4
+ # https://buildproven.ai/qa-architect
5
5
  set -e
6
6
 
7
7
  echo "🧠 Analyzing changes for optimal test strategy..."
@@ -1,39 +0,0 @@
1
- name: Auto Release
2
-
3
- on:
4
- push:
5
- tags:
6
- - 'v*'
7
-
8
- permissions:
9
- contents: write
10
-
11
- jobs:
12
- release:
13
- runs-on: ubuntu-latest
14
- steps:
15
- - uses: actions/checkout@v4
16
- with:
17
- fetch-depth: 0
18
-
19
- - name: Get previous tag
20
- id: prev_tag
21
- run: |
22
- PREV_TAG=$(git describe --tags --abbrev=0 HEAD^ 2>/dev/null || echo "")
23
- echo "tag=$PREV_TAG" >> $GITHUB_OUTPUT
24
-
25
- - name: Generate release notes
26
- run: |
27
- TAG=${GITHUB_REF#refs/tags/}
28
- PREV_TAG=${{ steps.prev_tag.outputs.tag }}
29
- if [ -n "$PREV_TAG" ]; then
30
- echo "## Changes since $PREV_TAG" > notes.md
31
- git log ${PREV_TAG}..${TAG} --pretty=format:"- %s" >> notes.md
32
- echo -e "\n\n**Full Changelog**: https://github.com/${{ github.repository }}/compare/${PREV_TAG}...${TAG}" >> notes.md
33
- else
34
- echo "Initial release" > notes.md
35
- fi
36
-
37
- - uses: softprops/action-gh-release@v2
38
- with:
39
- body_path: notes.md