From 2bb1fef543f2e8ceeac78c12184a9daedeed078e Mon Sep 17 00:00:00 2001 From: Mathias Date: Sat, 5 Sep 2026 14:42:59 +0200 Subject: [PATCH] chore(lint): adopt the canonical .golangci.yml from infra/ci-templates Canonical lives at infra ci-templates/golangci.yml, distributed by the infra#309 pattern: byte-identical copies, checksum drift gate in infra. Do not edit this file here -- edit the canonical and run `task ci:sync`. Verified locally before pushing, not pushed-and-hoped: golangci-lint v2.11.4 against a Go 1.26.1 toolchain (matching CI) reports 0 issues here. Also applies gofumpt, which this config enables and the golangci-lint v2 default set does not check at all. That gap is why the drift was invisible: earlier passes ran gofmt, which is weaker. Mechanical, deterministic, build+vet verified. --- .golangci.yml | 52 ++++++++++++++++++++++++ internal/mcp/stdio_test.go | 1 + internal/tools/file_write_branch_test.go | 10 +++-- 3 files changed, 59 insertions(+), 4 deletions(-) create mode 100644 .golangci.yml diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 0000000..2790f24 --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,52 @@ +# Canonical golangci-lint configuration for the estate's Go repos (infra#309 +# pattern: one canonical file here, a byte-identical copy in each adopter, +# and the drift gate in THIS repo comparing sha256). +# +# Why this exists: 26 Go repos, 3 had a lint config, and all three were +# different. The 23 without one ran golangci-lint's v2 default set, which +# does NOT include a formatter -- so gofmt/gofumpt drift went uncaught until +# it was found by hand (dma-cli#12: two files drifted, nothing flagged them). +# +# The two configs this replaces (cobalt-dingo, coo-agent) were near-identical +# copies of each other AND both invalid under v2: they carried v1-style +# `linters-settings` and `issues.exclude-rules` keys, which `golangci-lint +# config verify` rejects outright. Their revive settings and test exclusions +# were therefore not in effect. Consolidating fixes that too. +# +# Per-repo variation does NOT belong here -- this file must stay byte-identical +# across adopters so the gate is a checksum, not a diff a human has to judge. +# A repo with a genuine exception (agentsquad excludes its seeded-bug fixture +# tree, which exists precisely to contain broken code) keeps its own config and +# is not listed as an adopter. + +version: "2" + +linters: + default: none + enable: + - errcheck # unchecked errors + - govet # suspicious constructs + - staticcheck # broad static analysis + - unused # unused code + - misspell # spelling + - revive # idiomatic Go + - exhaustive # exhaustive switch on enums + + settings: + revive: + rules: + - name: var-naming + severity: warning + + exclusions: + rules: + # Test files: table-driven cases legitimately carry unused struct fields + # and long functions. + - path: _test\.go + linters: + - revive + - unused + +formatters: + enable: + - gofumpt diff --git a/internal/mcp/stdio_test.go b/internal/mcp/stdio_test.go index c939739..e771ebc 100644 --- a/internal/mcp/stdio_test.go +++ b/internal/mcp/stdio_test.go @@ -25,6 +25,7 @@ type echoTool struct{} func (echoTool) Descriptor() registry.ToolDescriptor { return registry.ToolDescriptor{Name: "echo", Description: "echoes its input"} } + func (echoTool) Call(_ context.Context, args json.RawMessage) (json.RawMessage, error) { return args, nil } diff --git a/internal/tools/file_write_branch_test.go b/internal/tools/file_write_branch_test.go index e6e896e..1963576 100644 --- a/internal/tools/file_write_branch_test.go +++ b/internal/tools/file_write_branch_test.go @@ -16,10 +16,12 @@ import ( "github.com/stretchr/testify/require" ) -const branchCheckExistsResp = `{"name":"feat/x","commit":{"id":"abc","url":"http://example.com"}}` -const createBranchResp = `{"name":"feat/new","commit":{"id":"abc","url":"http://example.com"}}` -const upsertFileResp = `{"content":{"path":"doc.md","sha":"filsha","html_url":"http://example.com/doc.md"},"commit":{"sha":"cmt1","html_url":"http://example.com/commit/cmt1"}}` -const getRepoResp = `{"name":"myrepo","full_name":"owner/myrepo","default_branch":"main"}` +const ( + branchCheckExistsResp = `{"name":"feat/x","commit":{"id":"abc","url":"http://example.com"}}` + createBranchResp = `{"name":"feat/new","commit":{"id":"abc","url":"http://example.com"}}` + upsertFileResp = `{"content":{"path":"doc.md","sha":"filsha","html_url":"http://example.com/doc.md"},"commit":{"sha":"cmt1","html_url":"http://example.com/commit/cmt1"}}` + getRepoResp = `{"name":"myrepo","full_name":"owner/myrepo","default_branch":"main"}` +) func TestFileWriteBranchCreatesBranchAndFile(t *testing.T) { mux := http.NewServeMux()