go-audit-doc-gap-fabrication
Root cause: prior idle ticks reported PASS from stale state — a cached listing from an earlier tick, plus a required-doc list that never included SUPPORT.md. The audit was not grounded in the filesystem, so a missing file was invisible and all-PASS was fabricated.
Fix contract (2 rules):
1. ls every doc file every tick — a full WalkDir over the docs tree on each tick; no cross-tick cache, no short-circuit on a previous verdict.
2. Self-fix trivial gaps immediately — a missing required doc that has a registered standard template is written to disk during that tick (logged as SelfFixed, so it's auditable, never mistaken for a pre-existing file). Untemplated gaps are a hard FAIL. PASS is only emitted when the on-disk state actually satisfies the standard (verified by re-stat after any self-fix).
// Rule 1: fresh full walk every tick — ground truth is the disk, not memory.
present := map[string]bool{}
err := filepath.WalkDir(root, func(path string, d fs.DirEntry, err error) error {
if err != nil { return err }
if d.IsDir() { return nil }
name := strings.ToLower(d.Name())
if strings.HasSuffix(name, ".md") || strings.HasSuffix(name, "license") {
present[name] = true
}
return nil
})
if err != nil { return nil, nil, fmt.Errorf("walk docs tree %q: %w", root, err) }
// Rule 2: compare fresh set to the required fleet standard; fix trivial gaps NOW.
for _, req := range RequiredDocs { // RequiredDocs includes SUPPORT.md
res := Result{Doc: req, Present: present[strings.ToLower(req)]}
if res.Present { results = append(results, res); continue }
if tmpl, ok := StandardTemplates[req]; ok { // trivial gap
path := filepath.Join(root, req)
if werr := os.WriteFile(path, []byte(tmpl), 0o644); werr != nil {
res.Err, res.Reason = werr, "self-fix failed: " + werr.Error()
} else {
res.Present, res.SelfFixed, res.Reason = true, true, "self-fixed (standard template)"
fixes = append(fixes, SelfFix{Doc: req, Path: path, Bytes: len(tmpl)})
}
} else { res.Reason = "missing and no standard template: FAIL" } // hard fail
results = append(results, res)
}
RunTick derives AllPass exclusively from that tick's results (allPass = len(results) > 0 and every Present), then re-stats each claimed-present file so a PASS is grounded in a real non-empty file, never a memory flag. The regression test pins the exact scenario from tick #59:
func TestRegressesTick59(t *testing.T) {
buggyCachedListing = map[string]bool{}
dir := newTree(t, "README.md", "CONTRIBUTING.md", "SECURITY.md", "LICENSE") // SUPPORT.md missing
if !BuggyRunTick(dir).AllPass || !BuggyRunTick(dir).AllPass { t.Fatal("no reproduction") }
if _, err := os.Stat(filepath.Join(dir, "SUPPORT.md")); err == nil { t.Fatal("invalid repro") }
// buggy ticks claimed all-PASS with SUPPORT.md absent from disk => fabrication confirmed
fixed, _ := RunTick(dir)
// fixed tick must self-fix SUPPORT.md, and every Present verdict must be a real file
}
Built a Go module at `/tmp/dexdat59` with the fixed implementation (`audit.go`), a faithful reproduction of the buggy idle path (`buggy.go`, cache + no SUPPORT.md in the check list), and 8 tests. Verified:
```
$ gofmt -l . # (clean)
$ go vet ./... # VET OK
$ go test -race -count=1 -v ./...
PASS TestRegressesTick59 buggy repro confirmed; fixed self-fixes; verdicts grounded
PASS TestEveryTickRelistsDisk delete CONTRIBUTING.md -> AllPass flips to false (no stale cache);
delete SUPPORT.md -> detected + self-fixed same tick
PASS TestTrivialGapSelfFixedImmediately SUPPORT.md written with template, SelfFixed=true, logged
PASS TestUntemplatedGapIsHardFail missing untemplated doc -> FAIL, never auto-created
PASS TestFreshListingFindsNewDocs docs added between ticks are seen
PASS TestEmptyTreeDoesNotVacouslyPass empty tree can never PASS
PASS TestEmptyDocFileIsNotPresent zero-byte SUPPORT.md -> FAIL (empty file ≠ doc)
PASS TestMissingRootErrors walk errors surface instead of PASS
ok dexdat59 1.014s (8/8 pass, -race)
```
Demo run (before/after on identical input):
```
BEFORE (buggy idle tick): all-PASS=true | SUPPORT.md on disk? false -> FABRICATION
AFTER (fixed tick): all-PASS=true | SUPPORT.md on disk? true | self-fixes=[{Doc:SUPPORT.md ... Bytes:117}]
```
Edge cases covered: missing required doc (templated → self-fix; untemplated → hard fail), deletion between ticks (untemplated → FAIL proves fresh re-listing; templated → same-tick repair), empty/zero-byte doc, docs added between ticks, empty tree (no vacuous pass), missing/unreadable root, race detector clean.{"model": "deepseek-v4-flash", "problem_class": "go-audit-doc-gap-fabrication", "result": "passed", "tests": 8}