Files
freemo 47b4c5fbfb
CI / push-validation (push) Successful in 10s
CI / helm (push) Successful in 28s
CI / build (push) Successful in 29s
CI / typecheck (push) Successful in 53s
CI / lint (push) Successful in 3m44s
CI / quality (push) Successful in 3m58s
CI / security (push) Successful in 4m12s
CI / e2e_tests (push) Successful in 4m49s
CI / integration_tests (push) Successful in 6m47s
CI / unit_tests (push) Successful in 8m3s
CI / docker (push) Successful in 1m31s
CI / coverage (push) Successful in 10m51s
CI / status-check (push) Successful in 1s
CI / benchmark-publish (push) Has been cancelled
CI / benchmark-regression (push) Has been cancelled
docs(skill): final pass — 2 new trees, expanded trees, reference file completions
SKILL.md (1,878 → 2,099 lines, 23 → 25 decision trees):

New 'Is my work done?' tree — comprehensive Definition of Done checklist
synthesising all requirements across implementation, three-level testing
(unit/integration/benchmarks), coverage ≥ 97%, five CI quality checks,
commit anatomy (atomic, body, footer), documentation (changelog, docstrings,
CONTRIBUTORS.md), PR fields (description, dep direction, Epic scope, milestone,
Type label), CI checks, and issue state transitions.

New 'What design pattern should I use?' tree — all 24 patterns from
CONTRIBUTING.md categorised across Creational (Factory, Abstract Factory,
Builder, Prototype, Singleton, Object Pool, DI), Structural (Adapter, Bridge,
Composite, Decorator, Facade, Flyweight, Proxy, Module), Behavioral (Chain of
Responsibility, Command, Iterator, Mediator, Memento, Observer, State, Strategy,
Template Method, Visitor, Null Object), and Architectural (Repository, Unit of
Work, Service Layer, MVC, CQRS, Event Sourcing, Specification). Every pattern
includes a when-to-use description and a CleverAgents-specific example.

Expand 'Am I about to write code?' — link to new patterns tree.
Expand 'Am I writing tests?' — add And/But/Outline Gherkin keywords with
examples, add Scenario Outline explanation, add naming good/bad examples with
anti-pattern list, expand integration test guidance with what good integration
tests exercise (CLI, DB, filesystem, service layer), expand Hypothesis section
with 6 specific use cases and recommended strategies to build.
Expand 'Am I about to commit?' — improve commit body guidance with a worked
example showing what to write (context, why this approach, risks, caveats).
Expand 'Am I triaging?' — add Epic/Legendary triage rules (no point estimates,
no milestone assignment, sign-off labels required for closure).

Add two branches to master decision tree for new trees.

Reference files:

references/testing/README.md (187 → 296 lines):
- Add Gherkin Quality Guidelines section: Given/When/Then semantics table,
  Scenario Outline explanation with example, naming rules with good/bad table,
  common anti-patterns (implementation details, multiple behaviors, missing Then)
- Add Property-Based Testing (Hypothesis) section: when-to-use table with 6
  specific CleverAgents use cases, recommended strategies to build, integration
  with Behave step definitions with worked example

references/langchain-langgraph/README.md (307 → 375 lines):
- Add RxPY Reactive Streams section: Subject vs BehaviorSubject vs ReplaySubject
  decision table with when-to-use and code examples, key operators table with
  use cases and code examples, backpressure management patterns (debounce vs
  throttle_first with examples), and clear list of what RxPY is NOT for

references/toolchain/README.md (271 → 272 lines):
- Add Hypothesis to tool table (property-based testing, nox -s unit_tests)

references/ci-cd/README.md (124 → 131 lines):
- Fix project-specific version number in release example (v3.6.0 → generic
  v<MAJOR>.<MINOR>.<PATCH>)
- Add release failure recovery procedure (verify secrets → build locally →
  delete tag → fix → re-tag)

ISSUES CLOSED: #0
2026-04-15 19:40:35 +00:00
..

Toolchain — CleverAgents Project

⚠️ Rules here override cleverthis-guidelines. Apply these exactly.


Toolchain Overview

Tool Role Entry point
nox Task automation — ALL quality operations nox or nox -s <session>
Hatch Project and environment management hatch env create, hatch build
pyproject.toml ALL project configuration (single source)
Pyright Static type checking (strict) nox -s typecheck
ruff Linting + auto-formatting nox -s lint, nox -s format
Slipcover Coverage measurement nox -s coverage_report
bandit Python security scanning nox -s security_scan
semgrep Cross-language security rules nox -s security_scan
vulture Unused code detection nox -s dead_code
Radon Complexity analysis nox -s complexity
ASV Airspeed Velocity benchmarks nox -s benchmark
Hypothesis Property-based testing nox -s unit_tests (integrated)
Behave BDD unit tests nox -s unit_tests
Robot Framework + pabot Integration + e2e tests nox -s integration_tests, nox -s e2e_tests
MkDocs Documentation builder nox -s docs
Commitizen Commit message guidance git cz
pre-commit Git hook automation scripts/setup-dev.sh

nox — The Only Entry Point

Never invoke any tool directly. All quality operations go through nox.

# WRONG:
behave features/
robot robot/
pyright src/
ruff check src/
bandit -r src/

# RIGHT:
nox -s unit_tests
nox -s integration_tests
nox -s typecheck
nox -s lint
nox -s security_scan

If a session is missing from noxfile.py → add it before running.

Complete session reference

nox                             # all default sessions (full quality gate)

# Quality:
nox -s lint                     # ruff linting + format check
nox -s format                   # auto-format with ruff
nox -s format -- --check        # format check only — CI mode
nox -s typecheck                # Pyright strict
nox -s security_scan            # bandit + semgrep + vulture
nox -s dead_code                # vulture dead code
nox -s complexity               # Radon (nightly quality sweep)

# Tests:
nox -s unit_tests               # Behave BDD
nox -s integration_tests        # Robot Framework via pabot
nox -s e2e_tests                # Robot Framework (real LLM keys)
nox -s coverage_report          # Slipcover (≥ 97% required)
nox -s benchmark                # ASV performance benchmarks
nox -s benchmark_regression     # ASV regression check

# Build / docs:
nox -s docs                     # MkDocs build
nox -s build                    # wheel distribution

Pyright — Static Type Checking

  • Configuration: pyproject.toml under [tool.pyright]
  • Run: nox -s typecheck
  • All code must pass Pyright strict mode
  • Zero tolerance for type errors

Absolute prohibitions

# This is NEVER acceptable:
x: int = some_value  # type: ignore

# This is also NEVER acceptable:
# Disabling Pyright in pyproject.toml:
# [tool.pyright]
# typeCheckingMode = "off"   ← PROHIBITED

If Pyright reports an error, fix the underlying code. There are no valid reasons to suppress type checking in this project. Not performance, not convenience, not temporary workarounds.


ruff — Linting and Formatting

  • Configuration: pyproject.toml under [tool.ruff]
  • Linting + format check: nox -s lint
  • Auto-format: nox -s format (modifies files)
  • Format check only (CI mode): nox -s format -- --check

Hatch — Project Management

hatch env create      # create the project's virtual environment
hatch build           # build the project (alternative to nox -s build)

All project configuration lives in pyproject.toml — no Makefiles, no wrapper shell scripts, no ad-hoc build commands. Commands must be native to the Hatch/nox toolchain.


pyproject.toml — Single Source of Truth

Every tool in this project is configured in pyproject.toml:

  • [tool.ruff] — linting and formatting rules
  • [tool.pyright] — type checking configuration
  • [tool.commitizen] — commit message format rules
  • [tool.coverage.report] — coverage threshold and exclusions
  • [tool.bandit] — security scan configuration
  • [tool.hatch.*] — environment and build configuration

Do not create separate config files (.pylintrc, setup.cfg, tox.ini, etc.). All configuration belongs in pyproject.toml.


Pre-commit Hooks

Configured in .pre-commit-config.yaml.

# Set up hooks (run once after cloning):
scripts/setup-dev.sh

Hooks run on every git commit and enforce:

  • Code formatting (ruff)
  • Linting (ruff)
  • Type checking (Pyright)
  • Security scanning (bandit)
  • Commit message format validation (Commitizen)

Never bypass with --no-verify. If a hook fails, fix the underlying issue.


Commitizen — Commit Messages

# Install (once):
npm install -g commitizen@2.8.6 cz-customizable@4.0.0

# Use (replaces git commit):
git cz

Commitizen guides you interactively through the Conventional Changelog format. Configuration lives in pyproject.toml under [tool.commitizen].

All CleverThis repositories use cz-customizable@4.0.0 as the adapter.


Import Rules (Python-specific for this project)

# ALL imports at the top of the file — always:
import os
import sys
from pathlib import Path
from typing import TYPE_CHECKING

from third_party import SomeClass

from mypackage.module import LocalClass

# The ONLY exception — type-only imports for circular dependency avoidance:
if TYPE_CHECKING:
    from mypackage.other_module import OtherType

# PROHIBITED — imports inside functions, methods, or blocks:
def some_function():
    import os          # ← NEVER
    from x import Y    # ← NEVER

if condition:
    import something   # ← NEVER

try:
    import optional    # ← NEVER
except ImportError:
    pass

Import style:

  • Prefer from module import ClassName over import module
  • No wildcard imports (from module import *)
  • ruff enforces import ordering and grouping (standard → third-party → local)

Error Handling (Python-specific examples)

Argument validation pattern (mandatory in all public/protected methods)

def process_data(self, data: list[str], threshold: int) -> None:
    """Process data with full argument validation first."""
    # Validate ALL arguments before any logic:
    if data is None:
        raise ValueError("data cannot be None")
    if not data:
        raise ValueError("data cannot be empty")
    if not all(isinstance(item, str) for item in data):
        raise TypeError("data must contain only strings")
    if threshold < 0 or threshold > 100:
        raise ValueError(f"threshold must be between 0 and 100, got {threshold}")

    # Only now: actual logic
    ...

Exception propagation rules

# WRONG — suppresses the error:
try:
    risky_operation()
except Exception:
    pass

# WRONG — logs and swallows:
try:
    risky_operation()
except Exception as e:
    logger.error(str(e))

# WRONG — returns None silently:
def find_user(user_id: int) -> User | None:
    try:
        return db.get(user_id)
    except DatabaseError:
        return None  # ← silent failure

# CORRECT — let it propagate:
risky_operation()

# CORRECT — catch only when you have real recovery logic:
try:
    result = risky_operation()
except TransientNetworkError:
    time.sleep(1)
    result = risky_operation()  # retry logic — meaningful handling