Claude Skill

precommit-setup

Configures pre-commit hooks for linting, type checking, formatting, and testing. Use when setting up a new project or adding quality gates to an existing one.

LLM Mart · 0 points · 5 views 0 listing impressions 0 install-command copies
Virus-scanned Reviewed automatically before listing.

Full trust report

Download athola-claude-night-market-plugins_attune_skills_precommit-setup-ff30fb8.zip · 8 KB
Part of athola/claude-night-market — 46 skills

Install

skills CLI npx skills add https://github.com/athola/claude-night-market/tree/master/plugins/attune/skills/precommit-setup
Claude Code claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install athola-claude-night-market@llmmart
Git git clone https://github.com/athola/claude-night-market.git

The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole athola/claude-night-market collection as a plugin from our marketplace. Git is the plain clone.

Skill manifest

Pre-commit Setup Skill

Configure a three-layer pre-commit quality system that enforces linting, type checking, and testing before every commit.

When To Use

  • Setting up a new project with code-quality enforcement
  • Adding pre-commit hooks to an existing project
  • Upgrading from basic linting to a full quality system
  • Setting up monorepo or plugin architecture with per-component quality checks
  • Updating pre-commit hook versions

When NOT To Use

  • Pre-commit hooks already configured and working optimally
  • Project does not use git version control
  • Team explicitly avoids pre-commit hooks for workflow reasons

Philosophy: Three-Layer Defense

The system is organised in three layers, each with a different cost / coverage tradeoff:

  • Layer 1: Standard hooks: fast global checks (50-200ms total). Lints and type-checks every staged file.
  • Layer 2: Component-specific checks: per-component lint, typecheck, and test (10-30s total). Only the components touched by the staged files are run.
  • Layer 3: Validation hooks: project-specific structure and pattern checks (varies). Catches violations that generic linters miss.

This layering keeps the fast feedback loop fast while still catching the slow / project-specific bugs before they land.

Module Loading

The detailed configuration patterns are in modules; load only the ones you need:

  • modules/standard-hooks.md: Layer 1 patterns for Python, Rust, and TypeScript (load when configuring base linters).
  • modules/component-level-hooks.md: Layer 2 monorepo scripts and pre-commit wiring (load when project has multiple components / plugins).
  • modules/validation-hooks.md: Layer 3 custom hooks and SKIP patterns (load when enforcing project conventions beyond linting).
  • modules/ci-integration.md: GitHub Actions workflow plus a complete .pre-commit-config.yaml example (load when wiring CI to mirror local checks).
  • modules/troubleshooting.md: timing tables, cache clearing, hook-failure recovery (load when hooks are slow or failing).

Workflow

1. Create Configuration Files

```bash

Create .pre-commit-config.yaml

python3 plugins/attune/scripts/attune_init.py \ --lang python \ --name my-project \ --path .

Create quality check scripts (for monorepos)

mkdir -p scripts chmod +x scripts/run-component-*.sh ```

2. Configure Python Type Checking

Create pyproject.toml with strict type checking:

```toml [tool.mypy] python_version = "3.12" warn_return_any = true warn_unused_configs = true disallow_untyped_defs = true strict = true

Per-component configuration

[[tool.mypy.overrides]] module = "plugins.*" strict = true ```

3. Configure Testing

```toml [tool.pytest.ini_options] testpaths = ["tests"] pythonpath = ["src"] addopts = [ "-v", # Verbose output "--strict-markers", # Strict marker enforcement "--cov=src", # Coverage for src/ "--cov-report=term", # Terminal coverage report ]

markers = [ "slow: marks tests as slow (deselect with '-m \"not slow\"')", "integration: marks tests as integration tests", ] ```

4. Install and Test Hooks

```bash

Install pre-commit tool

uv sync --extra dev

Install git hooks

uv run pre-commit install

Test on all files (first time)

uv run pre-commit run --all-files

Normal usage - test on staged files

git add . git commit -m "feat: add feature"

Hooks run automatically

```

5. Create Manual Quality Scripts

For full quality checks (CI/CD, monthly audits):

```bash #!/bin/bash

scripts/check-all-quality.sh: full quality check for all components

set -e

echo "=== Running Full Quality Checks ==="

./scripts/run-component-lint.sh --all ./scripts/run-component-typecheck.sh --all ./scripts/run-component-tests.sh --all

echo "=== All Quality Checks Passed ===" ```

Hook Execution Order

Pre-commit hooks run in this fixed order; all must pass for the commit to succeed:

  1. File validation (whitespace, EOF, YAML/TOML/JSON syntax)
  2. Security scanning (bandit)
  3. Global linting (ruff, all files)
  4. Global type checking (mypy, all files)
  5. Component linting (changed components only)
  6. Component type checking (changed components only)
  7. Component tests (changed components only)
  8. Custom validation (structure, patterns, etc.)

Best Practices

For New Projects

Start with strict settings from the beginning: they are easier to maintain over time. Configure type checking with strict = true in pyproject.toml, set up testing early (include pytest in pre-commit), and document the reason whenever you must skip a hook.

For Existing Projects

Use a gradual adoption strategy. Start with global checks (Layer 1), then add component-specific checks (Layer 2) once legacy issues are resolved. Use --no-verify only for true emergencies and document why.

For Monorepos and Plugin Architectures

Standardize per-component Makefiles for lint, typecheck, and test targets. Centralize common settings in a root pyproject.toml while allowing per-component overrides. Automate change detection so commits stay fast, and use progressive disclosure (summary first, detail on failure).

Related Skills

  • Skill(attune:project-init): Full project initialization
  • Skill(attune:workflow-setup): GitHub Actions setup
  • Skill(attune:makefile-generation): Generate component Makefiles
  • Skill(pensive:shell-review): Audit shell scripts for exit-code and safety issues

See Also

  • Quality Gates: three-layer validation: pre-commit hooks (formatting, linting), CI checks (tests, coverage), and PR review gates (code quality, security).

Exit Criteria

  • .pre-commit-config.yaml exists at the project root with hooks covering at minimum Layer 1 (whitespace, YAML/TOML/JSON syntax, global linting).
  • uv run pre-commit run --all-files exits 0 after the configuration is installed, confirming all hooks pass on the current codebase state.
  • git commit with a staged change triggers the pre-commit hooks automatically (verified by uv run pre-commit install exit code 0 and presence of .git/hooks/pre-commit).
  • Any --no-verify bypass is absent from the project's documented workflows; if one is found in existing scripts, it is flagged as a violation rather than silently accepted.
Files (claude-night-market)
  • modules
    • ci-integration.md 2.7 KB
      ---
      name: ci-integration
      description: GitHub Actions and GitLab CI workflow patterns mirroring local pre-commit checks.
      parent: precommit-setup
      load_when: configuring CI to run the same checks as pre-commit
      ---
      
      # CI Integration
      
      Verify CI runs the same thorough checks that pre-commit
      runs locally. Drift between local hooks and CI is the most
      common cause of "works on my machine" PRs.
      
      ## GitHub Actions
      
      \`\`\`yaml
      # .github/workflows/quality.yml
      name: Code Quality
      
      on: [push, pull_request]
      
      jobs:
        quality:
          runs-on: ubuntu-latest
          steps:
            - uses: actions/checkout@v4
      
            - name: Set up Python
              uses: actions/setup-python@v5
              with:
                python-version: '3.12'
      
            - name: Install uv
              run: pip install uv
      
            - name: Install dependencies
              run: uv sync
      
            - name: Run Comprehensive Quality Checks
              run: ./scripts/check-all-quality.sh
      
            - name: Upload Coverage
              uses: codecov/codecov-action@v4
              with:
                files: ./coverage.xml
      \`\`\`
      
      ## Complete Example: Python Monorepo
      
      \`\`\`yaml
      # .pre-commit-config.yaml
      repos:
        # Layer 1: Fast Global Checks
        - repo: https://github.com/pre-commit/pre-commit-hooks
          rev: v6.0.0
          hooks:
            - id: trailing-whitespace
            - id: end-of-file-fixer
            - id: check-yaml
            - id: check-toml
            - id: check-json
      
        - repo: https://github.com/astral-sh/ruff-pre-commit
          rev: v0.14.2
          hooks:
            - id: ruff
              args: [--fix]
            - id: ruff-format
      
        - repo: https://github.com/pre-commit/mirrors-mypy
          rev: v1.13.0
          hooks:
            - id: mypy
              args: [--ignore-missing-imports]
      
        - repo: https://github.com/PyCQA/bandit
          rev: 1.8.3
          hooks:
            - id: bandit
              args: [-c, pyproject.toml]
      
        # Layer 2: Component-Specific Checks
        - repo: local
          hooks:
            - id: run-component-lint
              name: Lint Changed Components
              entry: ./scripts/run-component-lint.sh
              language: system
              pass_filenames: false
              files: ^plugins/.*\\.py\$
      
            - id: run-component-typecheck
              name: Type Check Changed Components
              entry: ./scripts/run-component-typecheck.sh
              language: system
              pass_filenames: false
              files: ^plugins/.*\\.py\$
      
            - id: run-component-tests
              name: Test Changed Components
              entry: ./scripts/run-component-tests.sh
              language: system
              pass_filenames: false
              files: ^plugins/.*\\.(py|md)\$
      
        # Layer 3: Validation Hooks
        - repo: local
          hooks:
            - id: validate-plugin-structure
              name: Validate Plugin Structure
              entry: python3 scripts/validate_plugins.py
              language: system
              pass_filenames: false
              files: ^plugins/.*\$
      \`\`\`
      
    • component-level-hooks.md 4.9 KB
      ---
      name: component-level-hooks
      description: Layer 2 per-component pre-commit checks for monorepos and plugin architectures.
      parent: precommit-setup
      load_when: project has multiple components or plugins
      ---
      
      # Component-Specific Checks (Layer 2)
      
      For monorepos, plugin architectures, or projects with multiple
      components, add per-component quality checks. Each script
      detects changed components from staged files and runs lint /
      typecheck / test only against the affected components.
      
      ## Python Monorepo or Plugin Architecture
      
      Create three quality-check scripts under `scripts/`. All three
      share the same change-detection pattern.
      
      ### 1. Lint Changed Components (`scripts/run-component-lint.sh`)
      
      \`\`\`bash
      #!/bin/bash
      # Lint only changed components based on staged files
      
      set -euo pipefail
      
      # Detect changed components from staged files
      CHANGED_COMPONENTS=\$(git diff --cached --name-only | grep -E '^(plugins|components)/' | cut -d/ -f2 | sort -u) || true
      
      if [ -z "\$CHANGED_COMPONENTS" ]; then
          echo "No components changed"
          exit 0
      fi
      
      echo "Linting changed components: \$CHANGED_COMPONENTS"
      
      FAILED=()
      
      for component in \$CHANGED_COMPONENTS; do
          if [ -d "plugins/\$component" ]; then
              echo "Linting \$component..."
              # Capture exit code to properly propagate failures
              local exit_code=0
              if [ -f "plugins/\$component/Makefile" ] && grep -q "^lint:" "plugins/\$component/Makefile"; then
                  (cd "plugins/\$component" && make lint) || exit_code=\$?
              else
                  (cd "plugins/\$component" && uv run ruff check .) || exit_code=\$?
              fi
              if [ "\$exit_code" -ne 0 ]; then
                  FAILED+=("\$component")
              fi
          fi
      done
      
      if [ \${#FAILED[@]} -gt 0 ]; then
          echo "Lint failed for: \${FAILED[*]}"
          exit 1
      fi
      \`\`\`
      
      ### 2. Type Check Changed Components (`scripts/run-component-typecheck.sh`)
      
      \`\`\`bash
      #!/bin/bash
      # Type check only changed components
      
      set -euo pipefail
      
      CHANGED_COMPONENTS=\$(git diff --cached --name-only | grep -E '^(plugins|components)/' | cut -d/ -f2 | sort -u) || true
      
      if [ -z "\$CHANGED_COMPONENTS" ]; then
          exit 0
      fi
      
      echo "Type checking changed components: \$CHANGED_COMPONENTS"
      
      FAILED=()
      
      for component in \$CHANGED_COMPONENTS; do
          if [ -d "plugins/\$component" ]; then
              echo "Type checking \$component..."
              # Capture output and exit code separately to properly propagate failures
              local output
              local exit_code=0
              if [ -f "plugins/\$component/Makefile" ] && grep -q "^typecheck:" "plugins/\$component/Makefile"; then
                  output=\$(cd "plugins/\$component" && make typecheck 2>&1) || exit_code=\$?
              else
                  output=\$(cd "plugins/\$component" && uv run mypy src/ 2>&1) || exit_code=\$?
              fi
              # Display output (filter make noise)
              echo "\$output" | grep -v "^make\[" || true
              if [ "\$exit_code" -ne 0 ]; then
                  FAILED+=("\$component")
              fi
          fi
      done
      
      if [ \${#FAILED[@]} -gt 0 ]; then
          echo "Type check failed for: \${FAILED[*]}"
          exit 1
      fi
      \`\`\`
      
      ### 3. Test Changed Components (`scripts/run-component-tests.sh`)
      
      \`\`\`bash
      #!/bin/bash
      # Test only changed components
      
      set -euo pipefail
      
      CHANGED_COMPONENTS=\$(git diff --cached --name-only | grep -E '^(plugins|components)/' | cut -d/ -f2 | sort -u) || true
      
      if [ -z "\$CHANGED_COMPONENTS" ]; then
          exit 0
      fi
      
      echo "Testing changed components: \$CHANGED_COMPONENTS"
      
      FAILED=()
      
      for component in \$CHANGED_COMPONENTS; do
          if [ -d "plugins/\$component" ]; then
              echo "Testing \$component..."
              # Capture exit code to properly propagate failures
              local exit_code=0
              if [ -f "plugins/\$component/Makefile" ] && grep -q "^test:" "plugins/\$component/Makefile"; then
                  (cd "plugins/\$component" && make test) || exit_code=\$?
              else
                  (cd "plugins/\$component" && uv run pytest tests/) || exit_code=\$?
              fi
              if [ "\$exit_code" -ne 0 ]; then
                  FAILED+=("\$component")
              fi
          fi
      done
      
      if [ \${#FAILED[@]} -gt 0 ]; then
          echo "Tests failed for: \${FAILED[*]}"
          exit 1
      fi
      \`\`\`
      
      ## Add to Pre-commit Configuration
      
      \`\`\`yaml
      # .pre-commit-config.yaml (continued)
      
        # Layer 2: Component-Specific Quality Checks
        - repo: local
          hooks:
            - id: run-component-lint
              name: Lint Changed Components
              entry: ./scripts/run-component-lint.sh
              language: system
              pass_filenames: false
              files: ^(plugins|components)/.*\\.py\$
      
            - id: run-component-typecheck
              name: Type Check Changed Components
              entry: ./scripts/run-component-typecheck.sh
              language: system
              pass_filenames: false
              files: ^(plugins|components)/.*\\.py\$
      
            - id: run-component-tests
              name: Test Changed Components
              entry: ./scripts/run-component-tests.sh
              language: system
              pass_filenames: false
              files: ^(plugins|components)/.*\\.(py|md)\$
      \`\`\`
      
    • standard-hooks.md 1.5 KB
      ---
      name: standard-hooks
      description: Layer 1 fast global pre-commit checks for Python, Rust, and TypeScript projects.
      parent: precommit-setup
      load_when: configuring base linters
      ---
      
      # Standard Hooks (Layer 1)
      
      Fast global checks that run on every commit (typically 50-200ms total).
      
      ## Python Projects
      
      ### Basic Quality Checks
      
      1. **pre-commit-hooks**: file validation (trailing whitespace,
         EOF, YAML/TOML/JSON syntax)
      2. **ruff**: ultra-fast linting and formatting (~50ms)
      3. **ruff-format**: code formatting
      4. **mypy**: static type checking (~200ms)
      5. **bandit**: security scanning
      
      ### Configuration
      
      \`\`\`yaml
      # .pre-commit-config.yaml
      repos:
        - repo: https://github.com/pre-commit/pre-commit-hooks
          rev: v6.0.0
          hooks:
            - id: trailing-whitespace
            - id: end-of-file-fixer
            - id: check-yaml
            - id: check-toml
            - id: check-json
      
        - repo: https://github.com/astral-sh/ruff-pre-commit
          rev: v0.14.2
          hooks:
            - id: ruff
              args: [--fix]
            - id: ruff-format
      
        - repo: https://github.com/pre-commit/mirrors-mypy
          rev: v1.13.0
          hooks:
            - id: mypy
              args: [--ignore-missing-imports]
      
        - repo: https://github.com/PyCQA/bandit
          rev: 1.8.3
          hooks:
            - id: bandit
              args: [-c, pyproject.toml]
      \`\`\`
      
      ## Rust Projects
      
      1. **rustfmt**: code formatting
      2. **clippy**: linting
      3. **cargo-check**: compilation check
      
      ## TypeScript Projects
      
      1. **eslint**: linting
      2. **prettier**: code formatting
      3. **tsc**: type checking
      
    • troubleshooting.md 2.7 KB
      ---
      name: troubleshooting
      description: Performance tuning and failure-recovery patterns for slow or broken pre-commit hooks.
      parent: precommit-setup
      load_when: hooks are slow or failing
      ---
      
      # Performance and Troubleshooting
      
      ## Typical Timings
      
      | Check | Single Component | Multiple Components | All Components |
      |-------|------------------|---------------------|----------------|
      | Global Ruff | ~50ms | ~200ms | ~500ms |
      | Global Mypy | ~200ms | ~500ms | ~1s |
      | Component Lint | ~2-5s | ~4-10s | ~30-60s |
      | Component Typecheck | ~3-8s | ~6-16s | ~60-120s |
      | Component Tests | ~5-15s | ~10-30s | ~120-180s |
      | **Total** | **~10-30s** | **~20-60s** | **~2-5min** |
      
      ## Optimization Strategies
      
      1. **Only test changed components**: default behavior in
         the Layer 2 scripts.
      2. **Parallel execution**: pre-commit runs hooks
         concurrently when possible.
      3. **Caching**: dependencies cached by uv; mypy uses
         `.mypy_cache/`.
      4. **Incremental mypy**: enable `--incremental` for repeat
         commits in the same session.
      
      ## Hooks Too Slow
      
      Only changed components are checked by default. For even
      faster commits during active development:
      
      \`\`\`bash
      # Skip tests during development
      SKIP=run-component-tests git commit -m "WIP: feature development"
      
      # Run tests manually when ready
      ./scripts/run-component-tests.sh --changed
      \`\`\`
      
      ## Cache Issues
      
      \`\`\`bash
      # Clear pre-commit cache
      uv run pre-commit clean
      
      # Clear component caches
      find . -name "__pycache__" -type d -exec rm -rf {} +
      find . -name ".pytest_cache" -type d -exec rm -rf {} +
      find . -name ".mypy_cache" -type d -exec rm -rf {} +
      \`\`\`
      
      ## Hook Failures
      
      \`\`\`bash
      # See detailed output
      uv run pre-commit run --verbose --all-files
      
      # Run specific component checks manually
      cd plugins/my-component
      make lint
      make typecheck
      make test
      \`\`\`
      
      ## Import Errors in Tests
      
      \`\`\`toml
      # Ensure PYTHONPATH is set in pyproject.toml
      [tool.pytest.ini_options]
      pythonpath = ["src"]
      \`\`\`
      
      ## Type Checking Errors
      
      **Fix the implementation first.** A typecheck error
      almost always points at a real bug: a value that
      might be `None`, a return type that doesn't match,
      a function that lies about its signature. Loosening
      the typechecker hides the bug; it does not solve it.
      
      Only reach for per-module overrides as a last resort,
      after confirming the error reflects a deliberate
      escape hatch (e.g. interop with an untyped third-party
      library you cannot annotate). When you do override,
      narrow the scope tightly and leave a comment naming
      the underlying issue.
      
      \`\`\`toml
      # LAST RESORT: fix the implementation before reaching for this.
      # Narrow the scope to the offending module only; do not blanket-disable.
      [[tool.mypy.overrides]]
      module = "legacy_module.*"
      disallow_untyped_defs = false  # tracked: <issue link>
      \`\`\`
      
    • validation-hooks.md 1.8 KB
      ---
      name: validation-hooks
      description: Layer 3 custom validation hooks for project-specific structure and pattern checks.
      parent: precommit-setup
      load_when: enforcing project conventions or schema rules
      ---
      
      # Validation Hooks (Layer 3)
      
      Add custom validation hooks for project-specific requirements
      beyond what generic linters cover (structure, ADR compliance,
      schema invariants, security patterns).
      
      ## Example: Plugin Structure Validation
      
      \`\`\`yaml
        # Layer 3: Validation Hooks
        - repo: local
          hooks:
            - id: validate-plugin-structure
              name: Validate Plugin Structure
              entry: python3 scripts/validate_plugins.py
              language: system
              pass_filenames: false
              files: ^plugins/.*\$
      \`\`\`
      
      ## Custom Hook Patterns
      
      Add project-specific hooks for architectural or coverage rules:
      
      \`\`\`yaml
        - repo: local
          hooks:
            - id: check-architecture
              name: Validate Architecture Decisions
              entry: python3 scripts/check_architecture.py
              language: system
              pass_filenames: false
              files: ^(plugins|src)/.*\\.py\$
      
            - id: check-coverage
              name: Verify Test Coverage
              entry: python3 scripts/check_coverage.py
              language: system
              pass_filenames: false
              files: ^(plugins|src)/.*\\.py\$
      \`\`\`
      
      ## Hook Bypass Policy
      
      `SKIP=<hook> git commit` and `git commit --no-verify`
      **must not be used**. Hooks exist to keep the tree
      green; bypassing them moves broken code into history,
      where the next commit fights yesterday's bug instead
      of today's feature.
      
      If a hook fails, fix the underlying issue. If a hook
      is wrong (false positive, slow, irrelevant), fix the
      hook configuration. If commit pressure is the problem,
      land a smaller change. There is no supported workflow
      in this codebase that ends with a bypassed hook.
      
  • SKILL.md 6.9 KB
    ---
    name: precommit-setup
    description: Configures pre-commit hooks for linting, type checking, formatting, and testing. Use when setting up a new project or adding quality gates to an existing one.
    globs: "**/.pre-commit-config.yaml"
    alwaysApply: false
    # Custom metadata (not used by Claude for matching):
    model: sonnet
    tools:
    - Read
    - Write
    - Bash
    category: infrastructure
    tags:
    - pre-commit
    - quality-gates
    - linting
    - type-checking
    - testing
    complexity: intermediate
    model_hint: standard
    estimated_tokens: 1800
    progressive_loading: true
    modules:
    - modules/standard-hooks.md
    - modules/component-level-hooks.md
    - modules/validation-hooks.md
    - modules/ci-integration.md
    - modules/troubleshooting.md
    ---
    
    # Pre-commit Setup Skill
    
    Configure a three-layer pre-commit quality system that
    enforces linting, type checking, and testing before every
    commit.
    
    ## When To Use
    
    - Setting up a new project with code-quality enforcement
    - Adding pre-commit hooks to an existing project
    - Upgrading from basic linting to a full quality system
    - Setting up monorepo or plugin architecture with
      per-component quality checks
    - Updating pre-commit hook versions
    
    ## When NOT To Use
    
    - Pre-commit hooks already configured and working optimally
    - Project does not use git version control
    - Team explicitly avoids pre-commit hooks for workflow reasons
    
    ## Philosophy: Three-Layer Defense
    
    The system is organised in three layers, each with a
    different cost / coverage tradeoff:
    
    - **Layer 1: Standard hooks**: fast global checks
      (50-200ms total). Lints and type-checks every staged file.
    - **Layer 2: Component-specific checks**: per-component
      lint, typecheck, and test (10-30s total). Only the
      components touched by the staged files are run.
    - **Layer 3: Validation hooks**: project-specific
      structure and pattern checks (varies). Catches violations
      that generic linters miss.
    
    This layering keeps the fast feedback loop fast while still
    catching the slow / project-specific bugs before they land.
    
    ## Module Loading
    
    The detailed configuration patterns are in modules; load
    only the ones you need:
    
    - `modules/standard-hooks.md`: Layer 1 patterns for
      Python, Rust, and TypeScript (load when configuring base
      linters).
    - `modules/component-level-hooks.md`: Layer 2 monorepo
      scripts and pre-commit wiring (load when project has
      multiple components / plugins).
    - `modules/validation-hooks.md`: Layer 3 custom hooks
      and SKIP patterns (load when enforcing project conventions
      beyond linting).
    - `modules/ci-integration.md`: GitHub Actions workflow
      plus a complete `.pre-commit-config.yaml` example (load
      when wiring CI to mirror local checks).
    - `modules/troubleshooting.md`: timing tables, cache
      clearing, hook-failure recovery (load when hooks are slow
      or failing).
    
    ## Workflow
    
    ### 1. Create Configuration Files
    
    \`\`\`bash
    # Create .pre-commit-config.yaml
    python3 plugins/attune/scripts/attune_init.py \\
      --lang python \\
      --name my-project \\
      --path .
    
    # Create quality check scripts (for monorepos)
    mkdir -p scripts
    chmod +x scripts/run-component-*.sh
    \`\`\`
    
    ### 2. Configure Python Type Checking
    
    Create `pyproject.toml` with strict type checking:
    
    \`\`\`toml
    [tool.mypy]
    python_version = "3.12"
    warn_return_any = true
    warn_unused_configs = true
    disallow_untyped_defs = true
    strict = true
    
    # Per-component configuration
    [[tool.mypy.overrides]]
    module = "plugins.*"
    strict = true
    \`\`\`
    
    ### 3. Configure Testing
    
    \`\`\`toml
    [tool.pytest.ini_options]
    testpaths = ["tests"]
    pythonpath = ["src"]
    addopts = [
        "-v",                    # Verbose output
        "--strict-markers",      # Strict marker enforcement
        "--cov=src",             # Coverage for src/
        "--cov-report=term",     # Terminal coverage report
    ]
    
    markers = [
        "slow: marks tests as slow (deselect with '-m \\"not slow\\"')",
        "integration: marks tests as integration tests",
    ]
    \`\`\`
    
    ### 4. Install and Test Hooks
    
    \`\`\`bash
    # Install pre-commit tool
    uv sync --extra dev
    
    # Install git hooks
    uv run pre-commit install
    
    # Test on all files (first time)
    uv run pre-commit run --all-files
    
    # Normal usage - test on staged files
    git add .
    git commit -m "feat: add feature"
    # Hooks run automatically
    \`\`\`
    
    ### 5. Create Manual Quality Scripts
    
    For full quality checks (CI/CD, monthly audits):
    
    \`\`\`bash
    #!/bin/bash
    # scripts/check-all-quality.sh: full quality check for all components
    
    set -e
    
    echo "=== Running Full Quality Checks ==="
    
    ./scripts/run-component-lint.sh --all
    ./scripts/run-component-typecheck.sh --all
    ./scripts/run-component-tests.sh --all
    
    echo "=== All Quality Checks Passed ==="
    \`\`\`
    
    ## Hook Execution Order
    
    Pre-commit hooks run in this fixed order; all must pass for
    the commit to succeed:
    
    1. File validation (whitespace, EOF, YAML/TOML/JSON syntax)
    2. Security scanning (bandit)
    3. Global linting (ruff, all files)
    4. Global type checking (mypy, all files)
    5. Component linting (changed components only)
    6. Component type checking (changed components only)
    7. Component tests (changed components only)
    8. Custom validation (structure, patterns, etc.)
    
    ## Best Practices
    
    ### For New Projects
    
    Start with strict settings from the beginning: they are
    easier to maintain over time. Configure type checking with
    `strict = true` in `pyproject.toml`, set up testing early
    (include pytest in pre-commit), and document the reason
    whenever you must skip a hook.
    
    ### For Existing Projects
    
    Use a gradual adoption strategy. Start with global checks
    (Layer 1), then add component-specific checks (Layer 2)
    once legacy issues are resolved. Use `--no-verify` only for
    true emergencies and document why.
    
    ### For Monorepos and Plugin Architectures
    
    Standardize per-component Makefiles for `lint`, `typecheck`,
    and `test` targets. Centralize common settings in a root
    `pyproject.toml` while allowing per-component overrides.
    Automate change detection so commits stay fast, and use
    progressive disclosure (summary first, detail on failure).
    
    ## Related Skills
    
    - `Skill(attune:project-init)`: Full project initialization
    - `Skill(attune:workflow-setup)`: GitHub Actions setup
    - `Skill(attune:makefile-generation)`: Generate component
      Makefiles
    - `Skill(pensive:shell-review)`: Audit shell scripts for
      exit-code and safety issues
    
    ## See Also
    
    - **Quality Gates**: three-layer validation: pre-commit
      hooks (formatting, linting), CI checks (tests, coverage),
      and PR review gates (code quality, security).
    
    ## Exit Criteria
    
    - [ ] `.pre-commit-config.yaml` exists at the project root with hooks covering at minimum
      Layer 1 (whitespace, YAML/TOML/JSON syntax, global linting).
    - [ ] `uv run pre-commit run --all-files` exits 0 after the configuration is installed,
      confirming all hooks pass on the current codebase state.
    - [ ] `git commit` with a staged change triggers the pre-commit hooks automatically (verified
      by `uv run pre-commit install` exit code 0 and presence of `.git/hooks/pre-commit`).
    - [ ] Any `--no-verify` bypass is absent from the project's documented workflows; if one is
      found in existing scripts, it is flagged as a violation rather than silently accepted.
    

Comments (0)

Sign in to join the conversation.

No comments yet.

Reviews (0)

No reviews yet.

Related