Fix audit tool bootstrap and add per-run preflight

audit-code install-tools.sh:
- Buffer the opengrep release JSON before grep -m1; curl died with (23)
  under pipefail when grep quit early.
- Use ${m}: in the PowerShell block; $m: parsed as a scope-qualified var.
- On Arch, skip paru/yay when pacman -Q shows every package installed,
  since --needed still invokes sudo.
- Add --check-only (fast, installs nothing, non-zero naming missing tools)
  and --user-only (no system package managers, no sudo).

log-run.py (both skills): put the skill dir on sys.path so running it as
a script from any cwd no longer raises ModuleNotFoundError.

audit-terraform: move deps from requirements.txt into pyproject
dependency groups and add scripts/install-tools.sh (uv sync --group tools,
then check trivy, tflint, tofu, terragrunt, gh).

Both SKILL.md files gain a 0.5 Preflight step and call scripts through
uv run --project ${SKILL_DIR}. tools_unavailable is now a map of tool to
exact install command; audit-terraform skips trivy when absent and stops
with an install hint instead of crashing when tofu/terragrunt is missing.
This commit is contained in:
2026-09-22 15:21:28 -05:00
parent d3258b224a
commit 37fc3fb291
30 changed files with 1045 additions and 84 deletions
@@ -122,8 +122,11 @@ Upstream instructions: <https://opentofu.org/docs/intro/install/>,
<https://trivy.dev/latest/getting-started/installation/>,
<https://github.com/terraform-linters/tflint>, <https://cli.github.com/>.
Python dependencies are in `requirements.txt`: `python-hcl2`,
`beautifulsoup4`, `requests`, `pytest`.
Python dependencies live in `pyproject.toml`: the `tools` group
(`python-hcl2`, `beautifulsoup4`, `requests`) and the `dev` group (`pytest`).
`scripts/install-tools.sh` runs `uv sync --group tools` into
`${SKILL_DIR}/.venv/` and checks the native tools above;
`--check-only` does just the check.
## Subagents
@@ -184,7 +187,7 @@ indexed by terraform resource type:
Refresh from the AWS Security Hub docs:
```
python ${SKILL_DIR}/scripts/refresh-controls.py [--output-dir DIR]
uv run --project ${SKILL_DIR} python ${SKILL_DIR}/scripts/refresh-controls.py [--output-dir DIR]
```
`refresh-controls.py` fetches the FSBP standard index and the CIS benchmark
@@ -237,7 +240,7 @@ count off disk from each `findings-<agent>.json`:
```
echo '{"aws-bp-reviewer": {"model":"sonnet","input_tokens":N,"output_tokens":N,"duration_ms":N}}' \
| python ${SKILL_DIR}/scripts/log-run.py \
| uv run --project ${SKILL_DIR} python ${SKILL_DIR}/scripts/log-run.py \
--output-dir <OUTPUT> --run-id <hex8> --repo <REPO> \
--mode <local|ref> --usage-json -
```
@@ -247,7 +250,7 @@ echo '{"aws-bp-reviewer": {"model":"sonnet","input_tokens":N,"output_tokens":N,"
Read the log back with:
```
python ${SKILL_DIR}/scripts/review_stats.py
uv run --project ${SKILL_DIR} python ${SKILL_DIR}/scripts/review_stats.py
```
It prints JSON with `by_agent` (tokens, duration, runs, verdict counts,
@@ -270,16 +273,15 @@ and needs real `tofu` / `terragrunt`.
Run them with:
```
cd ${SKILL_DIR} && python -m pytest
cd ${SKILL_DIR} && uv run --group tools --group dev pytest
```
`uv run pytest` does **not** work here: `pyproject.toml` carries only
`[tool.ruff.lint.per-file-ignores]` and `[tool.pytest.ini_options]`, with no
`[project]` table, so uv exits with ``No `project` table found``. Test imports
resolve through `tests/conftest.py`, which puts the skill root on `sys.path`.
Test imports resolve through `tests/conftest.py`, which puts the skill root on
`sys.path`.
Lint with ruff; `collect-changes.py` and `refresh-controls.py` are exempted
from `E402` because both mutate `sys.path` before importing sibling modules.
Lint with ruff; `collect-changes.py`, `refresh-controls.py` and `log-run.py`
are exempted from `E402` because they mutate `sys.path` before importing
sibling modules.
### Layout