wiki-vault/wiki-context are an MCP-owned, managed surface — a second scanner risks interfering with how the vault MCP maintains its context. Remove the 'root' domain from DEFAULT_DOMAINS so a plain run no longer touches the vault; the --scan/--repo escape hatch still allows manual one-offs. Updated SKILL.md, check-catalog, findings-format, README, CLAUDE.md with the rationale. Default run: 3 domains, 37 repos, 54 findings (was 61); clears the vault-only false positives (herbygitea doc-mention, wiki-context uv-init stub).
85 lines
5.7 KiB
Markdown
85 lines
5.7 KiB
Markdown
# Check catalogue
|
|
|
|
Every check `scripts/audit.py` runs, what it looks for, the finding it emits,
|
|
and why it matters. All checks are read-only. Each finding carries a `check`
|
|
id (stable, dedup-friendly), a `category`, a `severity`, a `detail`, and a
|
|
remediation `hint`.
|
|
|
|
The conventions these checks enforce come from the repo-hygiene-remediation
|
|
plan's *Locked Decisions*: `.env` target mode **0660** + group **devprojects**;
|
|
secrets live in `.env`, not inline in compose; README = human onboarding,
|
|
CLAUDE.md = concise agent guide (not a README clone); docker compose stacks get
|
|
README only; prefer `main` over `master`; GitHub-destined repos are pushed
|
|
manually.
|
|
|
|
## Scope
|
|
|
|
Default domains: `homelab`, `pbs`, `docker`. The Obsidian vault (`wiki-vault`,
|
|
`wiki-context`) is **intentionally excluded** — it's an MCP-owned, managed
|
|
surface, so a second scanner risks interfering with how the vault MCP maintains
|
|
its context. Use `--scan` / `--repo` to point at it manually if ever needed;
|
|
don't re-add it to the defaults.
|
|
|
|
## AUDITABILITY (maps to Phase 3 — unblock un-auditable repos)
|
|
|
|
| check id | Looks for | Severity | Why |
|
|
|----------|-----------|----------|-----|
|
|
| `no-git` | A directory with real (non-dotfile) content but no `.git` | high | Can't be diffed, reviewed, or doc-audited until it's under version control. |
|
|
| `no-commits` | A `.git` exists but `HEAD` has zero commits | high | Everything is untracked; needs an initial commit pass. |
|
|
| `dubious-ownership` | `git` refuses the repo with "detected dubious ownership" | high | Repo is unusable to the current user. Fix ownership, or add a **scoped** `safe.directory <path>` — never the `*` wildcard, which disables the safety check globally. |
|
|
| `git-owner-drift` | `.git` owner differs from the directory owner (e.g. travadmin vs herbyadmin) | medium | Symptom of mixed-user operations; precedes dubious-ownership breakage. |
|
|
| `group-drift` | Directory group is not `devprojects` | low | Breaks the shared-group access model the dev tree relies on. |
|
|
|
|
## SECURITY (maps to Phase 2 — security remediation)
|
|
|
|
| check id | Looks for | Severity | Why |
|
|
|----------|-----------|----------|-----|
|
|
| `env-world-readable:<file>` | `.env` (or `.env.<env>`) readable by `other` | high | Secrets exposed to any local account. |
|
|
| `env-mode:<file>` | `.env` mode not in {0600, 0660} | medium | Doesn't meet the 0660/0600 target. |
|
|
| `env-group:<file>` | `.env` group is not `devprojects` | low | Group-access model drift. |
|
|
| `inline-secret:<file>` | A compose file assigns a secret-looking key (SECRET/PASSWORD/TOKEN/KEY/JWT/ENCRYPTION/SALT…) to a **literal** value (long hex/base64, not `${VAR}` and not a placeholder) | high | Secrets belong in a gitignored `.env`, not committed in compose. Heuristic — verify before acting; rotate if the repo was ever public. |
|
|
|
|
`.env.example` / `.env.sample` / `.env.template` / `.env.dist` are ignored
|
|
(they're meant to be committed and world-readable).
|
|
|
|
## CLEANUP (maps to Phase 4 — cross-repo cleanups)
|
|
|
|
| check id | Looks for | Severity | Why |
|
|
|----------|-----------|----------|-----|
|
|
| `uv-init-stub` | `main.py`/`hello.py` + `pyproject.toml` + (`uv.lock` or `.python-version`) in a repo with no `src/` and ≤2 `.py` files | low | Classic `uv init` residue left in non-Python repos; not on any build path. |
|
|
| `compose-legacy-name` | `docker-compose.yml` present, no `compose.yml` | low | Modern Compose prefers `compose.yml`. |
|
|
| `compose-rename-midflight` | Both `docker-compose.yml` and `compose.yml` present | medium | A rename was started but not finished; `git rm` the legacy file. |
|
|
| `stale-review-doc` | `GEMINI.md` or `*review*.md` at repo root | low | Stray review artifacts; move into a `reviews/` subdir or delete. |
|
|
| `herbygitea-residue` | The string `herbygitea` in any tracked file (the removed SSH alias) | medium | Dead remote/host alias; will break on next use. |
|
|
| `stray-dir` | Directory name ending `.broken` / `.backup-<date>` / `.bak` / `.old` | low | Scratch/backup cruft sitting in a domain folder. |
|
|
|
|
## GIT_STATE (review before commit/merge)
|
|
|
|
| check id | Looks for | Severity | Why |
|
|
|----------|-----------|----------|-----|
|
|
| `master-default` | `master` branch exists, no `main` | medium | House convention is `main`. |
|
|
| `docs-audit-branch` | A leftover `docs-audit*` branch | low | Residue from the one-time sweep; merge/push then delete. |
|
|
| `dirty-tree` | Uncommitted changes in the working tree | low | Sequence the doc/work commit deliberately; don't audit over churn. |
|
|
| `extra-worktrees` | More than one attached worktree | info | Possible stale worktrees to prune. |
|
|
| `no-upstream` | Current branch has no upstream | info | Expected for unpushed audit work; informational. |
|
|
| `unpushed-commits` | Commits ahead of upstream | info | Push when ready (manual for GitHub-destined repos). |
|
|
|
|
## DOCS (audit follow-up)
|
|
|
|
| check id | Looks for | Severity | Why |
|
|
|----------|-----------|----------|-----|
|
|
| `missing-readme` | No `README.md` in a git repo | medium | No human onboarding doc. |
|
|
| `missing-claude` | No `CLAUDE.md` in a git repo (skipped for the `docker` domain) | medium | No agent operating guide. Compose stacks intentionally get README only. |
|
|
| `claude-md-bloat` | `CLAUDE.md` > 200 lines | low | Likely a README clone — violates the role split (CLAUDE.md should be a concise, gotcha-focused agent guide). |
|
|
|
|
`claude-md-bloat` and the missing-doc checks flag **candidates** for the
|
|
semantic five-dimension review; they can't judge whether the prose is accurate.
|
|
|
|
## Extending
|
|
|
|
Add a `check_*(rep: RepoReport) -> None` function that appends `Finding`
|
|
objects, then register it in the `CHECKS` list. Keep it read-only and wrap
|
|
risky I/O — the orchestrator already catches exceptions per check so one bad
|
|
repo can't abort the sweep, but checks should fail soft on their own where they
|
|
can.
|