From a4fc7fc81ddb21494d4283896187f7663646cc1e Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 17 Jun 2026 18:44:24 +0000 Subject: [PATCH] Drop CodeQL from check.sh (enforced by codeql.yml) CodeQL is the slowest gate (~minutes) and depends on nothing else in the local pipeline. It was already enforced independently by the codeql.yml workflow, and ci.yml's check job never ran it anyway (no codeql on the hosted runner's PATH, so the step self-skipped there). Removing it from check.sh therefore loses no CI coverage and roughly halves the local gate wall-clock (~165s -> ~83s on a 4-core box). scripts/codeql_gate.py is kept so a code-scanning alert can still be reproduced locally on demand. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01TSGokAz8uYHj5PnWfYh8LP --- AGENTS.md | 2 +- scripts/check.sh | 19 ++++++------------- 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index d1efa405..038f4a57 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -25,7 +25,7 @@ uv run assembly --help # run the CLI from the locked environment Dev tooling is a PEP 735 `[dependency-groups]` group with `default-groups = ["dev"]`, not a `[project]` extra — `uv sync --extra dev` errors. -`scripts/check.sh` is the authoritative gate; keep this list in sync with it. It runs, in order: `uv lock --check` → `ruff check` → `ruff format --check` → `mypy` → `pyright` (src strict) → `pyright` (tests) → `vulture` (dead code) → `deptry` (dependency hygiene) → `lint-imports` (import-linter architecture contracts) → max-file-length (500 lines) → `xenon` (cyclomatic complexity: function max B, module avg A, project avg A) → `swiftlint` + swift compile (macOS only, skipped elsewhere) → `markdownlint` → `codespell` (spell-check code/comments/docs via `uvx`; config in `[tool.codespell]`) → `prettier` (init template JS/CSS) → `shellcheck` → `actionlint` + `zizmor` (workflow lint/audit) → `gitleaks` (secret scan) → generated `--show-code` compile gate → init template contract gate → unused snapshot/fixture gate (`scripts/unused_fixtures_gate.py`: orphaned `.ambr`/API fixtures, since xdist disables syrupy's own unused detection) → docs consistency gate (`scripts/docs_consistency_gate.py`: REFERENCE.md/README.md env vars, exit codes, and `assembly …` command refs stay in sync with the code) → docstring coverage gate (`scripts/docstring_coverage_gate.py`: public-API docstring ratchet, an `interrogate` stand-in that handles PEP 695 generics) → `brew audit --strict` (the shipped `Formula/assembly.rb`; self-skips without Homebrew) → `pytest` (90% branch coverage) → `diff-cover` (100% patch coverage vs `origin/main`) → **mutation gate** (diff-scoped: mutates each changed line and reruns the tests that cover it — a surviving mutant fails the gate, so changed lines need assertions that would *fail* if the line broke, not just coverage; suppress a genuinely unassertable line with `# pragma: no mutate`) → a "no new escape hatches" gate (`# type: ignore` / `# noqa` / `pragma: no cover` / `Any` / `cast(` / test skip/xfail/sleep, all **count-gated against the merge-base** so moving an existing hatch in a refactor doesn't false-positive but a net-new one fails) → **CodeQL gate** (`scripts/codeql_gate.py`: the same security + quality suites the CodeQL workflow uploads to GitHub's code-scanning/quality tabs, run locally over python/actions/javascript so alerts fail before push instead of on the PR; needs the CodeQL bundle on PATH — self-skips otherwise, `codeql.yml` covers CI, and the web session-start hook provisions it) → `uv build` + `twine check --strict`. The `vulture`/`deptry`/`lint-imports`/`xenon`, patch-coverage, and mutation stages catch the failures that `ruff`+`mypy` alone won't — don't claim the gate is green until the script prints `All checks passed.` +`scripts/check.sh` is the authoritative gate; keep this list in sync with it. It runs, in order: `uv lock --check` → `ruff check` → `ruff format --check` → `mypy` → `pyright` (src strict) → `pyright` (tests) → `vulture` (dead code) → `deptry` (dependency hygiene) → `lint-imports` (import-linter architecture contracts) → max-file-length (500 lines) → `xenon` (cyclomatic complexity: function max B, module avg A, project avg A) → `swiftlint` + swift compile (macOS only, skipped elsewhere) → `markdownlint` → `codespell` (spell-check code/comments/docs via `uvx`; config in `[tool.codespell]`) → `prettier` (init template JS/CSS) → `shellcheck` → `actionlint` + `zizmor` (workflow lint/audit) → `gitleaks` (secret scan) → generated `--show-code` compile gate → init template contract gate → unused snapshot/fixture gate (`scripts/unused_fixtures_gate.py`: orphaned `.ambr`/API fixtures, since xdist disables syrupy's own unused detection) → docs consistency gate (`scripts/docs_consistency_gate.py`: REFERENCE.md/README.md env vars, exit codes, and `assembly …` command refs stay in sync with the code) → docstring coverage gate (`scripts/docstring_coverage_gate.py`: public-API docstring ratchet, an `interrogate` stand-in that handles PEP 695 generics) → `brew audit --strict` (the shipped `Formula/assembly.rb`; self-skips without Homebrew) → `pytest` (90% branch coverage) → `diff-cover` (100% patch coverage vs `origin/main`) → **mutation gate** (diff-scoped: mutates each changed line and reruns the tests that cover it — a surviving mutant fails the gate, so changed lines need assertions that would *fail* if the line broke, not just coverage; suppress a genuinely unassertable line with `# pragma: no mutate`) → a "no new escape hatches" gate (`# type: ignore` / `# noqa` / `pragma: no cover` / `Any` / `cast(` / test skip/xfail/sleep, all **count-gated against the merge-base** so moving an existing hatch in a refactor doesn't false-positive but a net-new one fails) → `uv build` + `twine check --strict`. The `vulture`/`deptry`/`lint-imports`/`xenon`, patch-coverage, and mutation stages catch the failures that `ruff`+`mypy` alone won't — don't claim the gate is green until the script prints `All checks passed.` **CodeQL is intentionally NOT in this gate** — it's the slowest check (~minutes) and is enforced separately by the `codeql.yml` workflow (which also covers CI; `check.sh` self-skipped it on the hosted runner anyway), so dropping it keeps the local gate fast with no loss of CI coverage. `scripts/codeql_gate.py` still exists to reproduce a code-scanning alert locally (`uv run python scripts/codeql_gate.py`). **Commits are gated.** On success `check.sh` records a working-tree signature (`scripts/gate_marker.py record` → `.git/aai-gate-pass`), and a PreToolUse hook (`.claude/hooks/require-gate-before-commit.sh`) blocks `git commit` unless that signature still matches — so run the full gate to completion *before* committing (a single-file `pytest` does not satisfy it), and re-run it after any further edit. Iterate with the fast targeted commands above, gate once at the end. For a deliberate work-in-progress commit, prefix `AAI_ALLOW_COMMIT=1 git commit …`. diff --git a/scripts/check.sh b/scripts/check.sh index 1dffd1f4..2bb1b6e8 100755 --- a/scripts/check.sh +++ b/scripts/check.sh @@ -329,19 +329,12 @@ else echo " origin/main not found; skipping escape-hatch diff gate (CI provides it)" fi -echo "==> codeql (security + quality suites, mirrors codeql.yml minus swift)" -# Runs the same query suites the CodeQL workflow uploads to GitHub's code-scanning -# and quality tabs, so an alert fails here instead of surfacing on the PR after -# push. The CLI ships as a ~1 GB bundle with no PyPI/npm distribution, so this -# self-skips when absent — codeql.yml is the CI enforcement (the hosted runner's -# PATH has no codeql, so ci.yml's check job skips this too and the PR isn't -# double-scanned), and the web session-start hook provisions the bundle. Last of -# the analysis gates because it's the slowest (~minutes, not diff-scoped). -if command -v codeql >/dev/null 2>&1; then - uv run python scripts/codeql_gate.py -else - echo " codeql not found; skipping (codeql.yml runs it in CI; install: https://github.com/github/codeql-action/releases)" -fi +# CodeQL is NOT run here. It's the single slowest gate (~minutes) and is enforced in CI +# by codeql.yml, which runs the same security + quality suites on its own schedule and +# uploads them to GitHub's code-scanning/quality tabs. ci.yml's check job never ran it +# either (the hosted runner has no codeql on PATH, so this step self-skipped there), so +# dropping it from the local gate loses no CI coverage — it just keeps `check.sh` fast. +# To reproduce a code-scanning alert locally: `uv run python scripts/codeql_gate.py`. echo "==> build + twine check (PyPI publish readiness)" # Build sdist + wheel into ./dist, then validate the metadata and README render