{"record":{"id":"467fdbc7da59c6ae","repo":"gastownhall/beads","slug":"no-rules-to-compact","errorCode":null,"errorMessage":"no rules to compact","messagePattern":"no rules to compact","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/bd/rules.go","lineNumber":517,"sourceCode":"\tbestCount := 0\n\tfor w, c := range freq {\n\t\tif c > bestCount || (c == bestCount && w < bestWord) {\n\t\t\tbestWord = w\n\t\t\tbestCount = c\n\t\t}\n\t}\n\treturn bestWord\n}\n\n// roundTo2 rounds a float to 2 decimal places.\nfunc roundTo2(f float64) float64 {\n\treturn float64(int(f*100+0.5)) / 100\n}\n\n// CompactRules merges a group of rules into a single composite markdown file.\nfunc CompactRules(rules []RuleFile, groupLabel string) (string, error) {\n\tif len(rules) == 0 {\n\t\treturn \"\", fmt.Errorf(\"no rules to compact\")\n\t}\n\n\t// Collect and deduplicate Do/Don't lines\n\tseenDo := make(map[string]bool)\n\tseenDont := make(map[string]bool)\n\tvar doLines, dontLines []string\n\n\tfor _, r := range rules {\n\t\tfor _, line := range r.DoLines {\n\t\t\ttrimmed := strings.TrimSpace(line)\n\t\t\tif trimmed != \"\" && !seenDo[trimmed] {\n\t\t\t\tseenDo[trimmed] = true\n\t\t\t\tdoLines = append(doLines, trimmed)\n\t\t\t}\n\t\t}\n\t\tfor _, line := range r.DontLines {\n\t\t\ttrimmed := strings.TrimSpace(line)\n\t\t\tif trimmed != \"\" && !seenDont[trimmed] {","sourceCodeStart":499,"sourceCodeEnd":535,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/cmd/bd/rules.go#L499-L535","documentation":"CompactRules rejects an empty rules slice because merging zero rules cannot produce a meaningful composite markdown file. It is a guard against producing empty/degenerate output rather than a runtime failure.","triggerScenarios":"Calling CompactRules with a nil or empty []RuleFile, e.g. when the rules directory contained no parseable rules or was empty.","commonSituations":"Running `bd rules compact` in a repo with no .beads rules files; RunAudit returned an empty result and callers pass it straight through; filtering removed all rules before compaction.","solutions":["Check len(rules) > 0 before calling CompactRules.","Skip compaction (or print a friendly message) when the rules directory yields no RuleFiles.","Create at least one rule .md file in the rules directory."],"exampleFix":"// before\nout, err := CompactRules(rules, group)\n// after\nif len(rules) == 0 {\n    fmt.Fprintln(os.Stderr, \"no rules found; nothing to compact\")\n    return nil\n}\nout, err := CompactRules(rules, group)","handlingStrategy":"validation","validationCode":"if len(rules) == 0 {\n    return nil // or skip compaction with a friendly message\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Guard len(rules) > 0 before compaction.","Treat an empty rules directory as a no-op, not a compaction run.","Collect RuleFiles via RunAudit/parse loop and bail early if none parsed."],"tags":["validation","rules","empty-input"],"backgroundTag":"empty-input-error","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}