Files
claude-plugin/plugins/reviews/skills/audit-terraform/scripts/log-run.py
T
mroberts 37fc3fb291 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.
2026-09-22 15:21:28 -05:00

87 lines
3.0 KiB
Python

"""Append one subagent_run row per agent after the fan-out completes.
The orchestrator calls this once after all subagents return. It scans
<output-dir>/findings-<agent>.json for each agent listed in the
--usage-json payload, counts findings, and writes a subagent_run row to
runs.jsonl using token / duration metadata supplied by the orchestrator.
Usage:
python scripts/log-run.py \\
--output-dir <OUTPUT> --run-id <hex> --repo <path> --mode <local|ref> \\
--usage-json - <<JSON
{
"walkthrough-reviewer": {"model":"sonnet","input_tokens":1234,"output_tokens":567,"duration_ms":4500},
"aws-bp-reviewer": {"model":"sonnet","input_tokens":2345,"output_tokens":678,"duration_ms":5200}
}
JSON
`--log-path` defaults to ~/.claude/cache/audit-terraform/runs.jsonl.
"""
from __future__ import annotations
import argparse
import json
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
from scripts.telemetry import append_subagent_run
_DEFAULT_LOG = Path.home() / ".claude/cache/audit-terraform/runs.jsonl"
def _count_findings(path: Path) -> int:
if not path.exists():
return 0
try:
data = json.loads(path.read_text(encoding="utf-8"))
except json.JSONDecodeError:
return 0
if isinstance(data, dict):
findings = data.get("findings")
if isinstance(findings, list):
return len(findings)
elif isinstance(data, list):
return len(data)
return 0
def main(argv: list[str]) -> int:
p = argparse.ArgumentParser(description=__doc__.splitlines()[0])
p.add_argument("--output-dir", required=True, type=Path)
p.add_argument("--run-id", required=True)
p.add_argument("--repo", required=True)
p.add_argument("--mode", required=True, choices=["local", "ref"])
p.add_argument("--log-path", type=Path, default=_DEFAULT_LOG)
p.add_argument("--usage-json", required=True,
help="Path to JSON file, or '-' for stdin.")
args = p.parse_args(argv)
raw = sys.stdin.read() if args.usage_json == "-" else Path(args.usage_json).read_text(encoding="utf-8")
usage = json.loads(raw)
if not isinstance(usage, dict):
print("usage-json must be a JSON object keyed by agent name", file=sys.stderr)
return 2
for agent, meta in usage.items():
if not isinstance(meta, dict):
print(f"skipping {agent}: usage entry not an object", file=sys.stderr)
continue
findings_path = args.output_dir / f"findings-{agent}.json"
append_subagent_run(
args.log_path,
run_id=args.run_id, repo=args.repo, mode=args.mode, agent=agent,
model=str(meta.get("model", "?")),
input_tokens=int(meta.get("input_tokens", 0)),
output_tokens=int(meta.get("output_tokens", 0)),
duration_ms=int(meta.get("duration_ms", 0)),
finding_count=_count_findings(findings_path),
)
return 0
if __name__ == "__main__":
raise SystemExit(main(sys.argv[1:]))