Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions .github/workflows/code_standards.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
name: Code Standards

# Python Code Standards Compliance Framework (code-standards/).
# The framework itself is enforced strictly (examples + compliance tests must
# pass). The framework validator is also run against src/ in ADVISORY mode so
# the tiered report is visible without blocking merges on the existing baseline.

on:
push:
branches:
- main
pull_request:

jobs:

code-standards:
runs-on: ubuntu-latest
defaults:
run:
shell: bash -l {0}

steps:

- name: Checkout Repository
uses: actions/checkout@v4

- name: Install uv
uses: astral-sh/setup-uv@v4
with:
enable-cache: true

- name: Set up Python
run: uv python install 3.11

- name: Install dependencies
run: uv sync --frozen --extra dev

- name: Install ruff (framework tooling)
run: uv pip install ruff

# --- Strict: the framework's own artifacts must be compliant ---
- name: Compliant example is formatted
run: uv run ruff format --config code-standards/ruff.toml --check code-standards/examples/compliant.py

- name: Compliant example passes analysis
run: uv run ruff check --config code-standards/ruff.toml code-standards/examples/compliant.py

- name: Compliance tests
run: uv run pytest code-standards/tests/ -v

# --- Advisory: report the framework's findings on the existing codebase ---
- name: Framework report on src/ (advisory)
continue-on-error: true
run: ./code-standards/scripts/validate.sh src/
150 changes: 150 additions & 0 deletions code-standards/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
# Python Code Standards Compliance Framework

> **Drop-in ruff + pyright configuration for safety-critical Python development with Windsurf AI.**
>
> Framework version **1.0** — the Python port of
> [`COG-GTM/-C-Code-Standards-Compliance-Framework`](https://github.com/COG-GTM/-C-Code-Standards-Compliance-Framework),
> using the same patterns, severity model, and rule-ID numbering.

---

## What Is This?

A **complete, ready-to-use code standards enforcement system** for Python. It
combines:

1. **ruff format** — automatic code formatting (consistent style; Black-compatible)
2. **ruff check** — static analysis (bug + security detection)
3. **pyright** — IDE intelligence (type diagnostics, autocomplete, go-to-def)
4. **Severity Classification** — triage issues as Critical / Major / Minor
5. **Windsurf AI Rules** — intelligent code review with fix suggestions

It is the direct analog of the C/C++ framework. The mapping:

| Framework role | C/C++ tool | Python tool | Config file |
|----------------|-----------|-------------|-------------|
| Formatting | clang-format | **ruff format** | `ruff.toml` `[format]` |
| Static analysis | clang-tidy | **ruff check** | `ruff.toml` `[lint]` |
| Language server | clangd | **pyright** | `pyrightconfig.json` |

## Severity Classification

| Severity | Icon | Rule IDs | Action | Blocks Merge? | Exit code |
|----------|------|----------|--------|---------------|-----------|
| **Critical** | 🔴 | 20–29 | Must fix immediately | Yes | 1 |
| **Major** | 🟡 | 30–39 | Requires review | Recommended | 0 |
| **Minor** | 🟢 | 40–49 | Fix when convenient | No | 0 |

The **Critical gate** is enforced by `validate.sh` running `ruff check` restricted
to the critical rule codes (the analog of clang-tidy's `WarningsAsErrors`). See
[`rule-severity-mapping.yaml`](rule-severity-mapping.yaml) for the full mapping.

## Rule Reference (summary)

| Critical (🔴) | Major (🟡) | Minor (🟢) |
|--------------|-----------|-----------|
| 20 No swallowed errors | 30 Unsafe comparisons | 40 Formatting |
| 21 No injection | 31 Signature/docstring consistency | 41 Naming |
| 22 Guard None | 32 No dead code | 42 Explicit comparisons |
| 23 No resource leaks | 33 Control-flow errors | 43 Simplify booleans |
| 24 No mutable defaults | 34 Concurrency safety | 44 No else-after-return |
| 25 No use-before-assign | 35 Performance | 45 Modern syntax |
| 26 No insecure APIs | | 46 No unused imports/args |

Full detail with bad/good examples: [`docs/rule-reference.md`](docs/rule-reference.md).

## Quick Start

```bash
# 1. Install ruff (and optionally pyright)
pip install ruff # or: uv add --dev ruff

# 2. Validate a directory (format + tiered analysis)
./code-standards/scripts/validate.sh src/

# 3. Auto-fix formatting + safe lint fixes
./code-standards/scripts/validate.sh src/ --fix
```

Or invoke ruff directly with the framework config:

```bash
ruff format --config code-standards/ruff.toml --check src/
ruff check --config code-standards/ruff.toml src/
```

## Repository Contents

```
code-standards/
├── README.md # This documentation
├── ruff.toml # Formatting + static-analysis config
├── pyrightconfig.json # Language-server config (clangd analog)
├── rule-severity-mapping.yaml # Severity classification (version 1.0)
├── vscode-settings.json.template # VSCode/Windsurf editor settings
├── windsurf/
│ └── python-safety-critical-rules.md # Windsurf AI rules (trigger: always_on)
├── examples/
│ ├── compliant.py # Passes all checks
│ └── violations.py # Intentional violations (one per rule)
├── scripts/
│ └── validate.sh # Validation wrapper (tiered exit codes)
├── tests/
│ ├── __init__.py
│ └── test_compliance.py # Automated tests for the configs
└── docs/
├── rule-reference.md # Detailed rule documentation
└── setup.md # Setup / IDE integration guide
```

## CI/CD Integration

Add a job that runs the validator (fails on Critical + format):

```yaml
name: Code Standards
on: [push, pull_request]
jobs:
standards:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: astral-sh/setup-uv@v4
- run: uv sync --frozen --extra dev
- run: uv run ruff format --config code-standards/ruff.toml --check src/
- run: ./code-standards/scripts/validate.sh src/
- run: uv run pytest code-standards/tests/ -v
```

## Windsurf AI Integration

```bash
mkdir -p .windsurf/rules
cp code-standards/windsurf/python-safety-critical-rules.md .windsurf/rules/
```

Cascade then detects violations, classifies them by severity, reports them with
the Rule ID (e.g. "🔴 Critical - Rule 20 violation"), explains why, and suggests
a compliant fix.

## Adopting Repo-Wide

This framework is intentionally **additive and non-breaking**: `ruff.toml` uses
`line-length = 100` so `ruff format` output matches the repo's existing Black
config, and it is only applied when invoked with `--config`. To make it the
project's primary tooling, copy the `ruff.toml` settings into a root `ruff.toml`
or `[tool.ruff]` in `pyproject.toml`, and `pyrightconfig.json` to the root. See
[`docs/setup.md`](docs/setup.md).

## Requirements

| Tool | Minimum | Purpose |
|------|---------|---------|
| ruff | 0.6+ | Formatting + static analysis |
| pyright | 1.1+ (optional) | IDE type intelligence |
| Python | 3.10+ | Running the project/tests |
| pytest, PyYAML | — | Running compliance tests |

## License

Apache-2.0 (matches the AgentLab project license).
187 changes: 187 additions & 0 deletions code-standards/docs/rule-reference.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
# Rule Reference (Python)

Complete reference for all code standards rules. This is the Python
instantiation of the Code Standards Compliance Framework; rule IDs and
severities match the source C/C++ framework so findings are comparable across
languages.

## Overview

Rules are organized by severity:
- **Critical (Rule 20–29):** Safety/security issues that must be fixed
- **Major (Rule 30–39):** Quality issues that should be reviewed
- **Minor (Rule 40–49):** Style issues that improve maintainability

Each rule lists the ruff/pyright checks that enforce it.

---

## Critical Rules (Block Merge)

### Rule 20: Do Not Silently Swallow Errors
**Severity:** 🔴 Critical   **Checks:** `E722`, `BLE001`

Never use a bare `except:` or blind `except Exception: pass`.

```python
# ❌ BAD
try:
risky()
except:
pass

# ✅ GOOD
try:
risky()
except ValueError as err:
logger.error("risky failed: %s", err)
raise
```

### Rule 21: Prevent Injection / Unsafe Input
**Severity:** 🔴 Critical   **Checks:** `S602`, `S603`, `S604`, `S605`, `S608`

```python
# ❌ BAD
subprocess.run(f"ls {user_input}", shell=True)
# ✅ GOOD
subprocess.run(["ls", user_input], shell=False)
```

### Rule 22: Guard Optional / None Values
**Severity:** 🔴 Critical   **Checks:** `reportOptionalMemberAccess`, `reportOptionalSubscript` (pyright)

```python
# ❌ BAD
value = data.get("key")
return value.strip()
# ✅ GOOD
value = data.get("key")
if value is None:
return None
return value.strip()
```

### Rule 23: Prevent Resource Leaks
**Severity:** 🔴 Critical   **Checks:** `SIM115`

```python
# ❌ BAD
f = open(path)
data = f.read()
# ✅ GOOD
with open(path) as f:
data = f.read()
```

### Rule 24: Avoid Dangerous Shared Mutable State
**Severity:** 🔴 Critical   **Checks:** `B006`, `B008`

```python
# ❌ BAD
def add(item, bucket=[]):
bucket.append(item)
# ✅ GOOD
def add(item, bucket=None):
if bucket is None:
bucket = []
bucket.append(item)
```

### Rule 25: No Undefined / Use-Before-Assignment
**Severity:** 🔴 Critical   **Checks:** `F821`, `F822`, `F823`, `reportUnboundVariable`

```python
# ❌ BAD
if cond:
count = 10
return count
# ✅ GOOD
count = 0
if cond:
count = 10
return count
```

### Rule 26: Avoid Insecure APIs
**Severity:** 🔴 Critical   **Checks:** `S102`, `S307`, `S301`, `S506`, `S324`, `S311`

| Insecure | Secure |
|----------|--------|
| `eval`/`exec` | `ast.literal_eval` / explicit parsing |
| `pickle.loads(untrusted)` | `json.loads` |
| `yaml.load` | `yaml.safe_load` |
| `random` (secrets) | `secrets` |
| `md5`/`sha1` (security) | `sha256` |

---

## Major Rules (Requires Review)

### Rule 30: Avoid Unsafe Comparisons / Conversions
**Severity:** 🟡 Major   **Checks:** `E721`, `F632`

### Rule 31: Consistent Signatures & Docstrings
**Severity:** 🟡 Major   **Checks:** `darglint`

### Rule 32: No Redundant / Dead Code
**Severity:** 🟡 Major   **Checks:** `F811`, `F841`

### Rule 33: Prevent Control-Flow Errors
**Severity:** 🟡 Major   **Checks:** `F701`, `F702`, `F706`

### Rule 34: Concurrency / Shared-State Safety
**Severity:** 🟡 Major   **Checks:** `B006`

### Rule 35: Performance Issues
**Severity:** 🟡 Major   **Checks:** `PERF*`, `C4*`

---

## Minor Rules (Style)

### Rule 40: Consistent Formatting
**Severity:** 🟢 Minor   **Enforced by:** `ruff format` (`ruff.toml`)

### Rule 41: Naming Conventions
**Severity:** 🟢 Minor   **Checks:** `N` (pep8-naming)

| Kind | Convention | Example |
|------|------------|---------|
| Functions | `snake_case` | `process_data()` |
| Variables | `snake_case` | `buffer_size` |
| Constants | `UPPER_CASE` | `MAX_SIZE` |
| Classes | `PascalCase` | `DataBuffer` |

### Rule 42: Explicit Comparisons
**Severity:** 🟢 Minor   **Checks:** `E711`, `E712`, `E713`, `E714`

### Rule 43: Simplify Boolean Expressions
**Severity:** 🟢 Minor   **Checks:** `SIM`

### Rule 44: Avoid Else After Return
**Severity:** 🟢 Minor   **Checks:** `RET505`, `RET506`, `RET507`, `RET508`

### Rule 45: Use Modern Syntax
**Severity:** 🟢 Minor   **Checks:** `UP` (pyupgrade)

### Rule 46: Remove Unused Imports / Arguments
**Severity:** 🟢 Minor   **Checks:** `F401`, `ARG`

---

## Suppression Guide

```python
result = risky_call() # noqa: BLE001 (explain why)
```

File-level: add `# ruff: noqa: <CODE>` at the top of the file. Always document
why suppression is needed; prefer fixing over suppressing.

---

## References
- [ruff rules](https://docs.astral.sh/ruff/rules/)
- [pyright configuration](https://microsoft.github.io/pyright/#/configuration)
- [CWE](https://cwe.mitre.org/) · [OWASP Top 10](https://owasp.org/www-project-top-ten/)
Loading
Loading