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/.agents/skills/complexity-gate" ~/.claude/skills/jmagly-aiwg-complexity-gate && rm -rf "$T"
manifest: .agents/skills/complexity-gate/SKILL.md
source 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:

  1. Pass/fail status based on configured thresholds
  2. List of violations with file, metric, value, and threshold
  3. Exit code 0 (pass) or 1 (fail) for CI integration
  4. 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
    if/else/for/while/try
    nesting

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:
    /codebase-health
    (diagnostic dashboard vs. pass/fail gate)
  • Complements:
    /decompose-file
    (remediation for violations)
  • Pattern from:
    tdd-enforce
    skill (pre-commit hook integration)

Success Criteria

This command succeeds when:

  • Returns exit code 0 (pass) or 1 (fail)
  • JSON output mode for CI parsing
  • --changed-only
    mode for pre-commit hooks
  • --baseline
    mode for incremental adoption
  • Supports TypeScript, JavaScript, Python at minimum
  • Executes in <5s for
    --changed-only
    mode
  • 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