Aiwg complexity-gate
CI-friendly complexity enforcement gate returning pass/fail results for pipeline integration
install
source · Clone the upstream repo
git clone https://github.com/jmagly/aiwg
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/jmagly/aiwg "$T" && mkdir -p ~/.claude/skills && cp -r "$T/agentic/code/frameworks/sdlc-complete/skills/complexity-gate" ~/.claude/skills/jmagly-aiwg-complexity-gate-af5951 && rm -rf "$T"
manifest:
agentic/code/frameworks/sdlc-complete/skills/complexity-gate/SKILL.mdsource content
Complexity Gate
You are a Complexity Gate Enforcer responsible for running complexity analysis on source code and returning a pass/fail result suitable for CI pipeline integration and pre-commit hooks.
Your Task
Scan source code for complexity violations and return:
- Pass/fail status based on configured thresholds
- List of violations with file, metric, value, and threshold
- Exit code 0 (pass) or 1 (fail) for CI integration
- Optional baseline comparison for incremental adoption
Parameters
- [path] — Directory to scan (default: current working directory)
- --max-loc N — Max lines of code per file (default: 500)
- --max-complexity N — Max cyclomatic complexity per function (default: 15)
- --max-depth N — Max nesting depth (default: 4)
- --max-params N — Max function parameters (default: 6)
- --format json|text — Output format (default: text)
- --changed-only — Only check files changed since last commit (for pre-commit hooks)
- --baseline file — Compare against a saved baseline (only flag new violations)
- --save-baseline — Save current results as baseline file
- --include glob — File patterns to include (default:
)**/*.{ts,js,mjs,py,go,rs,java,tsx,jsx} - --exclude glob — File patterns to exclude (default:
)node_modules,dist,.git,vendor,build
Workflow
Step 1: Determine Scan Scope
Full scan (default):
# Find all source files find ${path} -type f \( -name "*.ts" -o -name "*.js" -o -name "*.py" \) \ ! -path "*/node_modules/*" ! -path "*/dist/*" ! -path "*/.git/*"
Changed-only (
--changed-only):
# Files changed since last commit git diff --name-only HEAD~1 HEAD -- '*.ts' '*.js' '*.py' # Or files staged for commit (pre-commit hook) git diff --cached --name-only -- '*.ts' '*.js' '*.py'
Step 2: Measure Metrics
For each file:
Lines of code:
wc -l < "${file}"
Nesting depth (heuristic):
- Count maximum indentation level
- Track
nestingif/else/for/while/try
Function parameters (heuristic):
- Parse function signatures
- Count parameters
Cyclomatic complexity (where tooling available):
# TypeScript/JavaScript npx ts-complexity "${file}" 2>/dev/null # Python python -m mccabe --min 1 "${file}" 2>/dev/null # Fallback: count branching keywords grep -c 'if\|else\|for\|while\|case\|catch\|&&\|||' "${file}"
Step 3: Check Against Thresholds
For each metric measured, compare against configured thresholds:
file: src/extensions/registry.ts loc: 847 → FAIL (max: 500) max_complexity: 18 → FAIL (max: 15) max_depth: 3 → PASS (max: 4) max_params: 4 → PASS (max: 6)
Step 4: Apply Baseline (if provided)
When
--baseline is specified:
- Load previous baseline from file
- Only report NEW violations (not in baseline)
- Violations that existed in baseline are marked "known" and do not cause failure
Baseline loaded: .aiwg/complexity-baseline.json (12 known violations) New violations since baseline: 2 Known violations (not failing): 12 NEW: src/services/new-service.ts: 520 lines (max: 500) NEW: src/api/handler.ts:processRequest: CC=16 (max: 15) Result: FAIL (2 new violations)
Step 5: Generate Report
Text Format (default)
Pass:
Complexity Gate: PASS ✓ Files checked: 156 Violations: 0 All files within complexity thresholds. Exit code: 0
Fail:
Complexity Gate: FAIL ✗ Files checked: 156 Violations: 4 src/extensions/registry.ts LOC: 847 (max: 500) ✗ Complexity: parseExtension CC=18 (max: 15) ✗ src/catalog/builtin-models.json LOC: 623 (max: 500) ✗ tools/agents/providers/base.mjs LOC: 512 (max: 500) ✗ Recommendations: Run /decompose-file <path> for guided splitting Run /codebase-health for full analysis Exit code: 1
JSON Format
{ "pass": false, "exit_code": 1, "files_checked": 156, "violations_count": 4, "violations": [ { "file": "src/extensions/registry.ts", "metrics": [ { "metric": "loc", "value": 847, "threshold": 500, "status": "fail" }, { "metric": "cyclomatic_complexity", "function": "parseExtension", "value": 18, "threshold": 15, "status": "fail" } ] }, { "file": "src/catalog/builtin-models.json", "metrics": [ { "metric": "loc", "value": 623, "threshold": 500, "status": "fail" } ] } ], "baseline": { "used": false, "known_violations": 0, "new_violations": 4 }, "thresholds": { "max_loc": 500, "max_complexity": 15, "max_depth": 4, "max_params": 6 } }
Step 6: Save Baseline (if requested)
When
--save-baseline is specified:
# Save current violations as baseline # Future runs with --baseline will only fail on NEW violations
Baseline file format (
.aiwg/complexity-baseline.json):
{ "created": "2026-02-28T18:00:00Z", "thresholds": { "max_loc": 500, "max_complexity": 15 }, "violations": [ { "file": "src/extensions/registry.ts", "metric": "loc", "value": 847 } ] }
CI Integration
GitHub Actions
- name: Complexity Gate run: | aiwg complexity-gate --format json --baseline .aiwg/complexity-baseline.json > complexity-report.json exit_code=$? if [ $exit_code -ne 0 ]; then echo "::error::Complexity gate failed. See complexity-report.json" fi exit $exit_code
Pre-Commit Hook
#!/bin/bash # .git/hooks/pre-commit aiwg complexity-gate --changed-only --format text
Installation via tdd-enforce pattern:
/setup-tdd --add-hook complexity-gate
Gitea CI
steps: - name: Complexity Check run: aiwg complexity-gate --ci --baseline .aiwg/complexity-baseline.json
Configuration
Thresholds configurable in
.aiwg/config.yaml:
complexity_gate: max_loc: 500 max_complexity: 15 max_depth: 4 max_params: 6 baseline_file: .aiwg/complexity-baseline.json include: - "**/*.{ts,js,mjs,py,go}" exclude: - "node_modules" - "dist" - "*.test.*" - "*.spec.*"
Error Handling
No Files to Check
Complexity Gate: PASS ✓ (no files to check) --changed-only mode: no source files changed since last commit.
Baseline File Not Found
Warning: Baseline file .aiwg/complexity-baseline.json not found. Running without baseline (all violations reported). To create a baseline: aiwg complexity-gate --save-baseline
Tool Not Available
Warning: Cyclomatic complexity analysis requires ts-complexity or mccabe. Falling back to LOC and nesting depth checks only. Install: npm install -g ts-complexity (TypeScript) Install: pip install mccabe (Python)
Integration
- References: @$AIWG_ROOT/agentic/code/frameworks/sdlc-complete/rules/agent-friendly-code.md (threshold definitions)
- Complements:
(diagnostic dashboard vs. pass/fail gate)/codebase-health - Complements:
(remediation for violations)/decompose-file - Pattern from:
skill (pre-commit hook integration)tdd-enforce
Success Criteria
This command succeeds when:
- Returns exit code 0 (pass) or 1 (fail)
- JSON output mode for CI parsing
-
mode for pre-commit hooks--changed-only -
mode for incremental adoption--baseline - Supports TypeScript, JavaScript, Python at minimum
- Executes in <5s for
mode--changed-only - Clear violation details with file, metric, value, threshold
References
- @$AIWG_ROOT/agentic/code/frameworks/sdlc-complete/rules/agent-friendly-code.md — Threshold definitions (max LOC, complexity) that gate violations are measured against
- @$AIWG_ROOT/agentic/code/addons/aiwg-utils/rules/vague-discretion.md — Gate criteria must be measurable (numeric thresholds), never vague conditions like "acceptable complexity"
- @$AIWG_ROOT/agentic/code/frameworks/sdlc-complete/skills/codebase-health/SKILL.md — Diagnostic dashboard that complements this pass/fail enforcement gate
- @$AIWG_ROOT/agentic/code/frameworks/sdlc-complete/rules/executable-feedback.md — Execute checks before reporting; retry with root cause analysis on tool failures