SDLC Validation
Run the validation pipeline at the specified level. Each check calls standard tools directly — no wrapper scripts needed.
Arguments
--syntax— Syntax only (fast, after every edit)--quick— Syntax + lint + tests (before commits)--pre-push— Full pipeline (before PRs). This is the default.
Preflight
Before running any check, verify the tool is available. Report missing tools clearly:
[SKIP] <tool> — not installed (run: <install command>)
Missing tools at --syntax level: warn but continue.
Missing tools at --quick or --pre-push level: report all missing tools, then stop.
Preflight checks
| Tool | Check command | Install command |
|---|---|---|
| ruff | which ruff |
pip install ruff |
| pytest | which pytest |
pip install pytest |
| mypy | which mypy |
pip install mypy |
| bandit | which bandit |
pip install bandit |
Also check:
- Virtual environment active:
which pythonshould contain.venv. If not, warn: "No virtual environment active. Run: source .venv/bin/activate" - Test directory exists:
ls tests/should find test files. Iftests/missing or empty, report: "No tests found. Tests are mandatory (Constitution Article 10.2)."
--syntax (after every edit)
Run these checks:
- Python AST check — verify all .py files parse:
python -c "
import ast, sys, pathlib
errors = []
for f in pathlib.Path('.').rglob('*.py'):
if '.venv' in str(f):
continue
try:
ast.parse(f.read_text())
except SyntaxError as e:
errors.append(f'{f}:{e.lineno}: {e.msg}')
if errors:
print('Syntax errors found:')
for e in errors:
print(f' {e}')
sys.exit(1)
print(f'Syntax OK — {len(list(pathlib.Path(\".\").rglob(\"*.py\")))} files checked')
"
- Ruff syntax errors only (if ruff installed):
ruff check . --select E9,F63,F7,F82
Report results:
[PASS] Syntax check — N files checked, 0 errors
[PASS] Ruff (syntax) — 0 issues
--quick (before commits)
Run all --syntax checks, then:
- Ruff full lint:
ruff check .
- Ruff format check:
ruff format --check .
- Technical debt scan:
grep -rn "TODO\|FIXME\|HACK\|XXX" --include="*.py" --exclude-dir=.venv . || true
If any matches found, report as failure (Production+) or warning (Prototype).
- Test execution:
pytest --tb=short -q
If pytest is not installed or no tests exist, this is a failure (not a skip).
- Import smoke test — verify the main module imports:
python -c "import app" 2>/dev/null || python -c "import main" 2>/dev/null || echo "No app/main module found (skipping import check)"
Report results:
[PASS] Ruff — 0 issues
[PASS] Format — all files formatted
[PASS] Technical debt — 0 markers
[PASS] Pytest — N passed, 0 failed
[PASS] Import check — app module imports cleanly
--pre-push (before PRs)
Run all --quick checks, then:
- Type checking:
mypy . --ignore-missing-imports
Or if mypy.ini or pyproject.toml configures mypy, just:
mypy .
- Security scan:
bandit -r . --exclude ./.venv -q
- Smoke test — start the app and verify it responds:
# Start the app in background
python app.py &
APP_PID=$!
sleep 3
# Check it's running
if kill -0 $APP_PID 2>/dev/null; then
echo "[PASS] App started (PID $APP_PID)"
# Try to hit an endpoint (adjust port to project)
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:18080/ 2>/dev/null || echo "000")
if [ "$HTTP_CODE" -ge 200 ] && [ "$HTTP_CODE" -lt 400 ]; then
echo "[PASS] Smoke test — HTTP $HTTP_CODE"
else
echo "[WARN] App started but endpoint returned HTTP $HTTP_CODE"
fi
kill $APP_PID 2>/dev/null
else
echo "[FAIL] App failed to start"
fi
If no app.py or main.py exists, skip the smoke test with:
[SKIP] Smoke test — no app entry point found (not a web application)
Summary Output
After all checks, print a summary:
=== SDLC Validation Summary (--pre-push) ===
[PASS] Syntax check — 12 files, 0 errors
[PASS] Ruff (syntax) — 0 issues
[PASS] Ruff (full) — 0 issues
[PASS] Format — all files formatted
[PASS] Technical debt — 0 markers
[PASS] Pytest — 30 passed, 0 failed
[PASS] Import check — clean
[PASS] Mypy — 0 errors
[PASS] Bandit — 0 issues
[PASS] Smoke test — HTTP 200
Result: 10 PASS, 0 FAIL, 0 SKIP
If any check is FAIL:
- Show the specific failures above the summary
- Do NOT proceed with commits or PRs
- Suggest fixes for each failure
Language Detection
Detect project language by scanning the project root:
*.pyfiles present → use Python checks (ruff, mypy, pytest, bandit)*.tsor*.jsfiles present → use JS checks (eslint, tsc, jest or vitest)*.gofiles present → use Go checks (go vet, staticcheck, go test)- Multiple languages → run checks for each detected language
Python is the primary implementation. Other languages follow the same structure with equivalent tools.