Documentation
¶
Overview ¶
Command gapaudit reconciles the `// GAP(<area>): <text>` markers left in the source tree against the `kind/gap` GitHub issues that are supposed to track them.
STYLE P3 requires every deliberate incompleteness — a fail-open XPath construct, an unimplemented validation branch, anything else recorded with a `GAP(` marker — to name a still-open tracking issue, so debt is greppable and ratchetable rather than fading into the prose around it. Nothing machine-checked enforces that promise: docs/WORKFLOW.md leaves it to the cartographer's backlog pass, which today means running `grep -rn "GAP("` and eyeballing the result against the open `kind/gap` issue list — a set difference, done by hand, over a list that only grows. PRINCIPLES 27 says repetitive deterministic work like that becomes a tool; this is that tool.
What it reports ¶
Three groups, each sorted for byte-identical reruns (STYLE D1):
- Markers with no OPEN tracking issue matched — the leak the rule exists to prevent. This includes a marker that only matches a CLOSED issue: STYLE P3 says a marker pointing at a closed issue is a dead end, so it is reported the same as an unmatched one, with the closed match named for context.
- OPEN `kind/gap` issues whose marker is no longer anywhere in the tree — a stale tracker: the gap was closed in code without closing the issue that tracked it.
- A per-area census of marker counts.
Matching is heuristic ¶
A marker is matched to an issue by its file path, or by a run of words from the marker's text, appearing in the issue's title or body (see [matches]). That is a resemblance test, not a citation graph: a marker with no match is reported as "no tracking issue found", never as "untracked" — the matcher has no way to rule out an issue that describes the same gap in different words, so the reader is the one who gets to call it truly untracked.
Usage ¶
go run ./tools/gapaudit [dir] < issues.json gh issue list --label kind/gap --state all --json number,title,state,body | go run ./tools/gapaudit
dir defaults to "." (the whole tree). Empty or absent stdin runs in marker-inventory-only mode: groups 1 and 2 are skipped (there is nothing to reconcile against) and the report says so.
It exits 0 on a clean run (regardless of what it finds — the findings are the report, not a failure) and 2 on an operational error: an unreadable file, a source file this tool's scanner cannot tokenize, or stdin that does not decode as the documented JSON shape.