diff --git a/.coveragerc b/.coveragerc new file mode 100644 index 0000000..d097391 --- /dev/null +++ b/.coveragerc @@ -0,0 +1,4 @@ +[run] +relative_files = true +omit = + scripts/test_*.py diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..165cb5c --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,11 @@ +version: 2 +updates: + # GitHub Actions — keeps the SHA-pinned actions current + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + open-pull-requests-limit: 5 + groups: + actions: + patterns: ["*"] diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a16a1d8..8074ff7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -5,18 +5,43 @@ on: branches: [main] pull_request: +permissions: + contents: read + jobs: test: runs-on: ubuntu-latest strategy: + fail-fast: false matrix: python-version: ["3.11", "3.12"] steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 with: python-version: ${{ matrix.python-version }} - - name: Install pytest - run: pip install pytest - - name: Run tests - run: pytest scripts/ -v + - name: Install + run: pip install pytest pytest-cov + - name: Run tests + coverage gate + run: pytest scripts/ -v --cov=scripts --cov-report=term-missing --cov-fail-under=85 + + coverage: + # Coverage badge + per-PR comment (self-contained, no third-party service). + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + steps: + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 + with: + python-version: "3.12" + - run: pip install pytest coverage + - name: Measure coverage + run: | + coverage run -m pytest scripts/ + coverage report + - name: Coverage badge + PR comment + uses: py-cov-action/python-coverage-comment-action@cc6cde2639ed103404ce0da9e75114ae9561e691 # v3 + with: + GITHUB_TOKEN: ${{ github.token }} diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 0000000..10afb38 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,35 @@ +name: CodeQL + +on: + push: + branches: [main] + pull_request: + branches: [main] + schedule: + - cron: "27 3 * * 1" # weekly, Monday 03:27 UTC + +permissions: + contents: read + +jobs: + analyze: + name: Analyze (python) + runs-on: ubuntu-latest + permissions: + security-events: write + actions: read + contents: read + steps: + - name: Checkout + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + + - name: Initialize CodeQL + uses: github/codeql-action/init@dd903d2e4f5405488e5ef1422510ee31c8b32357 # v3 + with: + languages: python + queries: security-extended + + - name: Perform CodeQL analysis + uses: github/codeql-action/analyze@dd903d2e4f5405488e5ef1422510ee31c8b32357 # v3 + with: + category: "/language:python" diff --git a/.gitignore b/.gitignore index 75c6182..5e368a5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,8 @@ __pycache__/ *.pyc .pytest_cache/ + +# coverage artifacts +.coverage +coverage.xml +htmlcov/ diff --git a/README.md b/README.md index f79c153..9fa470c 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,11 @@ # Fleet Mode +[![CI](https://github.com/Jott2121/fleet-mode/actions/workflows/ci.yml/badge.svg)](https://github.com/Jott2121/fleet-mode/actions/workflows/ci.yml) +[![CodeQL](https://github.com/Jott2121/fleet-mode/actions/workflows/codeql.yml/badge.svg)](https://github.com/Jott2121/fleet-mode/actions/workflows/codeql.yml) +[![Coverage](https://raw.githubusercontent.com/Jott2121/fleet-mode/python-coverage-comment-action-data/badge.svg)](https://github.com/Jott2121/fleet-mode/actions/workflows/ci.yml) +[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE) +[![Python](https://img.shields.io/badge/Python-3.11+-3776AB?logo=python&logoColor=white)](https://www.python.org/) + **A measured doctrine for orchestrating AI agents, and knowing when not to.** ![Fleet Mode](assets/banner.png) @@ -82,6 +88,16 @@ single careful agent. Fleet Mode is the discipline that keeps the wins (parallel review, hard gates) and drops the cargo-culting (parallel writers, self-grading, unbounded agent swarms). It scales *to the task*, not to the hype. +## Reliability & security + +A doctrine about hard gates runs its own: + +- **Coverage-gated tests** — the receipt-writer script is tested on Python 3.11–3.12 and the build fails below the coverage floor (currently 92% covered). +- **CodeQL** — `security-extended` static analysis on every push, PR, and weekly; findings surface in the Security tab. +- **Pinned supply chain** — GitHub Actions pinned to commit SHAs, kept current by **Dependabot**. +- **Branch protection** — `main` requires CI + CodeQL to pass before a merge. +- **Disclosure policy** — see [SECURITY.md](SECURITY.md); private reporting is enabled. + ## License MIT, copyright 2026 Jeff Otterson. See [LICENSE](LICENSE). diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..12b89be --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,37 @@ +# Security Policy + +## Supported versions + +`fleet-mode` is actively maintained. Security fixes target the latest version on +the `main` branch. + +| Version | Supported | +| ---------------- | --------- | +| latest (`main`) | ✅ | +| older tags | ❌ | + +## Reporting a vulnerability + +Please **do not** open a public issue for security vulnerabilities. + +Report privately through GitHub's +[**Report a vulnerability**](https://github.com/Jott2121/fleet-mode/security/advisories/new) +flow (the repository's **Security → Advisories** tab). I aim to acknowledge +reports within 72 hours and to ship a fix or mitigation for confirmed issues as +quickly as is practical. + +When reporting, please include: + +- a description of the issue and its impact, +- steps to reproduce (a minimal proof-of-concept if possible), and +- any suggested remediation. + +## Scope + +`fleet-mode` ships a Claude Code skill plus helper scripts (notably the +hash-chained receipt writer). Findings of particular interest: tampering with +the append-only receipt ledger, unsafe file handling in the scripts, and +supply-chain risks in CI (this repository pins its GitHub Actions to commit SHAs +and runs CodeQL + Dependabot to reduce that surface). + +Thanks for helping keep it solid.