Skip to content
Merged
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
21 changes: 20 additions & 1 deletion .claude/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@
"Bash(ruff check *)",
"Bash(ruff format *)",
"Bash(mypy *)",
"Bash(pyright *)",
"Bash(vulture *)",
"Bash(deptry *)",
"Bash(lint-imports *)",
"Bash(xenon *)",
"Bash(diff-cover *)",
"Bash(prettier *)",
"Bash(swiftlint *)",
"Bash(pytest *)",
"Bash(pre-commit run *)",
"Bash(./scripts/check.sh)",
Expand All @@ -36,7 +44,18 @@
"mcp__assemblyai-docs__search_docs",
"mcp__assemblyai-docs__get_pages",
"mcp__assemblyai-docs__get_api_reference",
"mcp__assemblyai-docs__list_sections"
"mcp__assemblyai-docs__list_sections",
"mcp__github__pull_request_read",
"mcp__github__list_pull_requests",
"mcp__github__search_pull_requests",
"mcp__github__get_commit",
"mcp__github__list_commits",
"mcp__github__get_file_contents",
"mcp__github__actions_list",
"mcp__github__actions_get",
"mcp__github__get_job_logs",
"mcp__github__issue_read",
"mcp__github__list_issues"
],
"deny": [
"Read(.env)",
Expand Down
7 changes: 5 additions & 2 deletions .claude/skills/check/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ Run the project's canonical verification gate and report the result.
./scripts/check.sh
```

This runs, in order: `ruff check` → `ruff format --check` → `mypy` (src + tests) → `markdownlint` (excludes generated `docs/`) → `shellcheck install.sh` → `pytest` with a **90% branch-coverage gate** (`--cov-fail-under=90`, excluding `e2e` and `install_script` markers) → `uv build` + `twine check --strict`. Everything runs through `uv run` against the locked environment.
This runs, in order: `uv lock --check` → `ruff check` → `ruff format --check` → `mypy` (src + tests) → `pyright` (src strict, then tests) → `vulture` (dead code) → `deptry` (dependency hygiene) → `lint-imports` (architecture contracts) → `xenon` (cyclomatic complexity, max grade B / project avg A) → `swiftlint` + swift compile (macOS only) → `markdownlint` (excludes generated `docs/`) → `prettier` (init template JS/CSS) → `shellcheck install.sh scripts/check.sh` → generated `--show-code` compile gate → init template contract gate → `pytest` with a **90% branch-coverage gate** (`--cov-fail-under=90`, excluding `e2e`/`install`/`install_script` markers) → `diff-cover` (100% patch coverage vs `origin/main`) → a "no new escape hatches" diff gate → `uv build` + `twine check --strict`. Everything Python runs through `uv run` against the locked environment.

Heads-up on the stages `ruff`+`mypy` don't cover: `vulture` flags unused code, `deptry` flags unused/missing/misplaced dependencies, `lint-imports` enforces the import-architecture contracts in `.importlinter`, and `xenon` fails any function over cyclomatic-complexity grade B (CC > 10). These are the ones that most often surprise an otherwise-clean change.

2. If anything fails, fix it and re-run `./scripts/check.sh` until it passes. Do not claim success until the script prints `All checks passed.`

Expand All @@ -31,5 +33,6 @@ uv run pytest -m install_script # builds a wheel and runs install.sh for real;

## Notes

- If `shellcheck` isn't installed locally, `check.sh` skips it with a notice (CI still runs it) — that's expected, not a failure.
- External linters that aren't Python deps — `shellcheck`, `prettier`, `swiftlint`/`swiftc` — self-skip with a notice when not installed (CI still runs them); that's expected, not a failure. `swiftlint`/`swiftc` also no-op off macOS.
- `diff-cover` and the escape-hatch gate self-skip when `origin/main` isn't present (e.g. a shallow branch-only clone); CI provides the base ref.
- Report the final outcome with the actual tail of the output, not a summary from memory.
6 changes: 5 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@ This project uses [uv](https://docs.astral.sh/uv/). **Run every Python tool thro
```sh
uv sync --extra dev # create/refresh the venv with dev dependencies
uv run aai --help # run the CLI from the locked environment
./scripts/check.sh # the full gate CI runs: ruff + mypy + markdownlint + prettier + shellcheck + pytest(+coverage) + build/twine
./scripts/check.sh # the full gate CI runs (scripts/check.sh is the source of truth)
```

`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) → `xenon` (cyclomatic complexity, max grade B / project avg A) → `swiftlint` + swift compile (macOS only, skipped elsewhere) → `markdownlint` → `prettier` (init template JS/CSS) → `shellcheck` → generated `--show-code` compile gate → init template contract gate → `pytest` (90% branch coverage) → `diff-cover` (100% patch coverage vs `origin/main`) → a "no new escape hatches" diff gate (`# type: ignore` / `# noqa` / `pragma: no cover` / net-new `Any` / `cast(`) → `uv build` + `twine check --strict`. The `vulture`/`deptry`/`lint-imports`/`xenon` and patch-coverage stages catch the failures that `ruff`+`mypy` alone won't — don't claim the gate is green until the script prints `All checks passed.`

Individual tools (all via `uv run`):

```sh
Expand All @@ -37,6 +39,8 @@ uv run pytest -m install_script # builds a wheel and runs install.sh for real;

`check.sh` runs `-m "not e2e and not install_script"` with a **90% branch-coverage gate** (`--cov-fail-under=90`). New code generally needs tests to clear that gate.

CLI output is pinned by **syrupy snapshot tests** (`tests/__snapshots__/*.ambr`). Changing help text, tables, or rendered output will fail those tests until you regenerate them with `uv run pytest --snapshot-update` and commit the updated `.ambr` files. The auto-format hook only touches `*.py`, and pre-commit's whitespace fixers deliberately skip `tests/__snapshots__/` (syrupy's indentation must stay byte-for-byte), so never hand-edit a snapshot — always regenerate.

## Naming & packaging gotchas

- The **package/module** is `aai_cli`; the **distribution** name is `aai-cli`; the **console command** is `aai` (`[project.scripts] aai = "aai_cli.main:run"`).
Expand Down
8 changes: 7 additions & 1 deletion scripts/check.sh
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,13 @@ echo "==> markdownlint (docs/ is generated, so excluded)"
markdownlint "**/*.md" --ignore docs --ignore node_modules --ignore .pytest_cache

echo "==> prettier (init template JS/CSS)"
prettier --check "aai_cli/init/templates/**/*.{js,css}"
# CI's runner has prettier on PATH; locally it's skipped with a notice if not
# installed, matching how shellcheck/swiftlint self-skip above.
if command -v prettier >/dev/null 2>&1; then
prettier --check "aai_cli/init/templates/**/*.{js,css}"
else
echo " prettier not found; skipping (CI runs it)"
fi

echo "==> shellcheck (install.sh)"
# Static-lint the public install script and this gate script. CI's ubuntu runner ships shellcheck;
Expand Down
Loading