From 249055fe99746ac9ecc6398909393a22a69acf71 Mon Sep 17 00:00:00 2001 From: Travis Herbranson Date: Sat, 23 May 2026 06:50:37 -0400 Subject: [PATCH] Fix .gitignore swallowing references/findings-format.md The findings-*.md rule (for generated timestamped reports) also matched the findings-format.md reference doc, so it was never tracked. Scope the rule to digit-prefixed names (findings-[0-9]*) and add the missing reference. --- .gitignore | 10 ++- .../references/findings-format.md | 85 +++++++++++++++++++ 2 files changed, 91 insertions(+), 4 deletions(-) create mode 100644 repo-hygiene-audit/references/findings-format.md diff --git a/.gitignore b/.gitignore index 8ce9074..76b25ba 100644 --- a/.gitignore +++ b/.gitignore @@ -10,10 +10,12 @@ __pycache__/ venv/ env/ -# Generated audit reports (timestamped runs are not source) -findings-*.md -findings-*.json -findings-*.txt +# Generated audit reports (timestamped runs are not source). +# Scoped to digit-prefixed names so the references/findings-format.md +# doc is NOT swallowed. +findings-[0-9]*.md +findings-[0-9]*.json +findings-[0-9]*.txt # Environment / secrets .env diff --git a/repo-hygiene-audit/references/findings-format.md b/repo-hygiene-audit/references/findings-format.md new file mode 100644 index 0000000..b910287 --- /dev/null +++ b/repo-hygiene-audit/references/findings-format.md @@ -0,0 +1,85 @@ +# Findings output format + +Three renderers, one finding model. Pick the format for the consumer: + +- `text` — terminal triage. Summary line, full `INVENTORY` (every repo, clean + ones included), then findings grouped by category. +- `md` — phase-mapped markdown. Each finding is a `- [ ]` checkbox under the + remediation-plan phase heading it belongs to, so a run pastes straight into + the project plan as actionable items. +- `json` — machine-readable for week-over-week diffing and automation. + +## Finding model + +Every finding is one record: + +| Field | Meaning | +|-------|---------| +| `domain` | `homelab` / `pbs` / `docker` (the Obsidian vault is out of scope by default — see check-catalog.md) | +| `repo` | Directory name within the domain | +| `path` | Absolute path | +| `category` | `SECURITY` / `AUDITABILITY` / `CLEANUP` / `GIT_STATE` / `DOCS` | +| `severity` | `high` / `medium` / `low` / `info` | +| `check` | Stable check id (e.g. `no-git`, `env-world-readable:.env`) | +| `detail` | Human-readable description of what was found | +| `hint` | Suggested remediation (informational — the skill does not apply it) | +| `key` | `domain/repo:check` — stable identifier for dedup/diffing (JSON only) | + +The `key` is deliberately stable across runs: a finding that persists keeps the +same key, so diffing two JSON runs cleanly separates *new drift* (keys that +appeared) from *remediated items* (keys that disappeared). + +## Category → phase mapping + +This is how findings line up with the repo-hygiene-remediation plan, so the +recurring review feeds the same backlog structure the original audit used: + +| Category | Plan phase | +|----------|-----------| +| `SECURITY` | Phase 2 — Security remediation | +| `AUDITABILITY` | Phase 3 — Unblock un-auditable repos | +| `CLEANUP` | Phase 4 — Cross-repo cleanups | +| `GIT_STATE` | Git state (review before commit/merge) | +| `DOCS` | Docs (audit follow-up) | + +## JSON shape + +```json +{ + "generated": "2026-05-22T23:05:00", + "host": "herbys-dev", + "repos_scanned": 39, + "summary": { + "by_severity": {"high": 11, "medium": 19, "low": 23, "info": 9}, + "by_category": {"SECURITY": 5, "AUDITABILITY": 9, "CLEANUP": 8, + "GIT_STATE": 27, "DOCS": 13} + }, + "inventory": [ + {"domain": "docker", "repo": "authelia", "path": "...", + "is_git": false, "owner": "root", "git_owner": "", "group": "root", + "branch": "", "finding_count": 2} + ], + "findings": [ + {"domain": "docker", "repo": "authelia", "path": "...", + "category": "AUDITABILITY", "severity": "high", "check": "no-git", + "detail": "directory holds real content but has no .git", + "hint": "git init + initial commit ...", "key": "docker/authelia:no-git"} + ] +} +``` + +## Diffing two runs + +```bash +python scripts/audit.py --format json -o this-week.json +# ... a week later ... +python scripts/audit.py --format json -o next-week.json + +python3 - <<'PY' +import json +a = {f["key"] for f in json.load(open("this-week.json"))["findings"]} +b = {f["key"] for f in json.load(open("next-week.json"))["findings"]} +print("NEW drift :", sorted(b - a)) +print("REMEDIATED :", sorted(a - b)) +PY +```