package main import ( "os" "path/filepath" "reflect" "strings" "testing" ) // The reports in testdata/hq are copies of real issue reports of novox/hq, as they stood on 2026-10-10, // chosen for their shapes: a bracketed list with commas inside parentheses, quoted block items, an // apostrophe in prose inside a bracketed list, a `resolved:` date, a replay, an empty list, a wontfix. func readSample(t *testing.T, folder string) string { t.Helper() raw, err := os.ReadFile(filepath.Join("testdata", "hq", IssuesFolder, folder, "00-report.md")) if err != nil { t.Fatal(err) } return string(raw) } func TestTheFrontmatterOfRealReportsIsReadAsWritten(t *testing.T) { cases := []struct { folder string want Report }{ {"362-two-merges-seconds-apart-left-their-delivery-waiting-for-a-person", Report{ Number: 362, Status: StatusResolved, Opened: "2026-10-10", Title: "Two catalogue merges seconds apart left their delivery waiting for a person", // A bracketed list whose entries hold commas inside parentheses: two entries, not four. LocatedIn: []string{"mesh-catalog modules/mesh-delivery (holder.go deliveryWalking)", "mesh-controller cmd/mesh-controller (upgrades.go SourceMoved, release_plan.go laterOnTheBranch)"}, // A scalar is one entry, commas and all, as hq's own check reads it. FixedBy: []string{"mesh-catalog#171, mesh-controller#197"}, AmendedDesign: []string{"03-DESIGN/01-to-be/47-delivery-from-commit-to-delivered.md"}, Replay: "R362", }}, {"007-an-installed-package-is-not-a-capability", Report{ Number: 7, Status: StatusResolved, Opened: "2026-08-23", Title: "An installed package is not an available capability", LocatedIn: []string{"hal (the instance)", "mesh-host internal/bootstrap (preflight asks the daemon)", "mesh-controller internal/catalogue (capabilities)"}, // Quoted block items, each holding colons and commas, taken whole and unquoted. FixedBy: []string{ "the instance only: PR #962 — incus hook. Merged, ran on one node in 6s of a 60s budget; pipeline #6832 green in 48s. The class remains open.", "partly, on the mesh: mesh-host 73c010e, 9d8239a — preflight and the profile detectors ask the daemon, not the package (installed-but-broken reports absent)", "the class, on the mesh: a manifest declares capabilities, an action declares verify (ADR 0005), and a module's own assertions are the lab's verdict (design 01). The old arrangement is replaced module by module, so its count is never taken", }, AmendedDesign: []string{"03-DESIGN/01-to-be/01-end-to-end-testing.md"}, }}, {"080-a-cache-grant-lets-the-consumer-flush-the-server", Report{ Number: 80, Status: StatusResolved, Opened: "2026-09-22", Title: "A cache grant lets the consumer flush the server", // An apostrophe inside prose in a bracketed list is no quote: the list closes on its own line. LocatedIn: []string{"mesh-catalog modules/redis (the provisioner's ACL)"}, FixedBy: []string{"mesh-catalog multiple-fixes (the consumer's ACL user loses the dangerous command category); proven by " + "the grant end-to-end bed, which now asserts a write outside the consumer's keys and FLUSHALL are refused"}, }}, {"043-a-module-cannot-be-given-the-meshs-own-queues", Report{ Number: 43, Status: StatusResolved, Opened: "2026-09-12", Closed: "2026-09-12", Title: "A module cannot be given an account for the mesh's own queues", LocatedIn: []string{"mesh-controller (the verb existed)"}, FixedBy: []string{"nothing — the capability already existed and the wrong verb was used"}, }}, {"236-the-catalogue-check-passes-a-manifest-the-host-refuses", Report{ Number: 236, Status: StatusResolved, Opened: "2026-10-04", Title: "The catalogue check passes a manifest the host refuses", LocatedIn: []string{"mesh-controller cmd/mesh-controller (the merge gate)"}, FixedBy: []string{"novox/mesh-controller PR #96 (bbd442c, the merge gate, ADR 0237)"}, Replay: "R236", }}, {"345-a-reminder-window-shows-transparent-and-empty", Report{ Number: 345, Status: StatusDiagnosing, Opened: "2026-10-09", Title: "A calendar reminder shows as a transparent, empty window, and the mesh had no tool to look at it", }}, {"150-a-route-is-contributed-before-its-module-is-taken", Report{ Number: 150, Status: StatusWontfix, Opened: "2026-09-29", Title: "A route is contributed before its module is taken", LocatedIn: []string{"mesh-controller internal/catalogue/declaration.go (contributions are emitted for an assigned module, taken or not)"}, }}, } for _, c := range cases { got, err := ParseReport(c.folder, readSample(t, c.folder)) if err != nil { t.Fatalf("%s: %v", c.folder, err) } if got.Folder != IssuesFolder+"/"+c.folder || got.Path != got.Folder+"/00-report.md" { t.Fatalf("%s: folder %q path %q", c.folder, got.Folder, got.Path) } if got.Body == "" || strings.Contains(got.Body, "\n# ") || strings.HasPrefix(got.Body, "# ") || strings.HasPrefix(got.Body, "---") { t.Fatalf("%s: the body keeps its frontmatter or title: %.80q", c.folder, got.Body) } if len(got.Odd) != 0 { t.Fatalf("%s: odd %v", c.folder, got.Odd) } // The title's number and separator are stripped, whatever the separator: "362. ", "043 — ". got.Folder, got.Path, got.Body, got.Issues, got.Decisions = "", "", "", nil, nil if !reflect.DeepEqual(*got, c.want) { t.Fatalf("%s:\n got %+v\n want %+v", c.folder, *got, c.want) } } } func TestAReportNamesTheIssuesAndDecisionsItCites(t *testing.T) { r, err := ParseReport("362-two-merges-seconds-apart-left-their-delivery-waiting-for-a-person", readSample(t, "362-two-merges-seconds-apart-left-their-delivery-waiting-for-a-person")) if err != nil { t.Fatal(err) } for _, n := range r.Issues { if n == 362 { t.Fatal("an issue names itself") } } for _, d := range r.Decisions { if len(d) != 4 { t.Fatalf("decision %q", d) } } text := "---\nstatus: open\nopened: 2026-10-10\n---\n# 9. t\n\nSee issue 155, 04-ISSUES/203-x/00-report.md and ADR 0275 " + "(02-DECISIONS/0019-how.md), and issue 155 again, and issue 9 itself." r, err = ParseReport("009-t", text) if err != nil { t.Fatal(err) } if !reflect.DeepEqual(r.Issues, []uint64{155, 203}) || !reflect.DeepEqual(r.Decisions, []string{"0019", "0275"}) { t.Fatalf("issues %v decisions %v", r.Issues, r.Decisions) } } func TestWhatMakesAReportUnreadableAndWhatIsOnlyOdd(t *testing.T) { refused := map[string]string{ "no frontmatter": "# 9. t\n\nbody", "no status": "---\nopened: 2026-10-10\n---\n# 9. t\n", "a sixth status": "---\nstatus: fixed\n---\n# 9. t\n", "no title": "---\nstatus: open\n---\nbody only\n", "an empty title": "---\nstatus: open\n---\n# 9.\n", "no folder shape": "", } for what, text := range refused { folder := "009-t" if what == "no folder shape" { folder, text = "nine-t", "---\nstatus: open\n---\n# t\n" } if _, err := ParseReport(folder, text); err == nil { t.Errorf("%s was read", what) } } r, err := ParseReport("009-t", "---\nstatus: open\nopened: yesterday\nseverity: high\nreplay: R1\nreplay: R2\n---\n# 12 — t\n\nbody") if err != nil { t.Fatal(err) } if r.Opened != "" || r.Replay != "R2" || r.Title != "t" { t.Fatalf("%+v", r) } if r, _ := ParseReport("009-t", "---\nstatus: open\n---\n# 2 nodes share a name\n"); r.Title != "2 nodes share a name" { t.Fatalf("a title starting with a number: %q", r.Title) } if r, _ := ParseReport("009-t", "---\nstatus: open\n---\n# 9 nodes share a name\n"); r.Title != "nodes share a name" { t.Fatalf("a title starting with the folder's number: %q", r.Title) } odd := strings.Join(r.Odd, "\n") for _, want := range []string{"opened: \"yesterday\" is not a date", "frontmatter keys not imported: severity", "numbered 12; the folder is 9"} { if !strings.Contains(odd, want) { t.Fatalf("odd %q lacks %q", odd, want) } } } func TestTheFrontmatterShapesHqUses(t *testing.T) { front, body, ok := frontmatter("---\n" + "a: [x, \"y, z\", (p, q) r]\n" + "b:\n - one\n - \"two: 2\"\n" + "c: plain scalar\n wrapped onto a line\n" + "d:\n" + "e: []\n" + "f: [over,\n two lines]\n" + "g: 'it''s'\n" + "---\nbody\n") if !ok || body != "body\n" { t.Fatalf("ok %v body %q", ok, body) } want := map[string][]string{ "a": {"x", "y, z", "(p, q) r"}, "b": {"one", "two: 2"}, "c": {"plain scalar wrapped onto a line"}, "d": nil, "e": nil, "f": {"over", "two lines"}, "g": {"it's"}, } for k, v := range want { if !reflect.DeepEqual(front[k], v) { t.Errorf("%s: %q, want %q", k, front[k], v) } } }