From e86a66a8091fe47da07b4175dd824608c3969344 Mon Sep 17 00:00:00 2001 From: Tri Lam Date: Wed, 13 May 2026 12:44:23 -0700 Subject: [PATCH 1/6] Add make check fast loop and exemplar package rubric Tighten the developer feedback loop and codify what "good" looks like so M1 sets a pattern future packages copy rather than diverge from. - Makefile: new `check` target (fmt + tidy-check + lint + test) for the inner loop, complementing `ci` (license-check + vet + lint + test + build) which remains the pre-PR gate. New `tidy-check` runs `go mod tidy -diff` non-mutatingly so dependency drift fails fast. - go.sum: 54 transitive-checksum additions surfaced by tidy-check on first run. Bundled here so the new gate lands green; no source change. - AGENTS.md: new "Exemplar packages" section names internal/pipeline/ (lands with M1) as the canonical runtime shape and lists the rubric (layout, doc comments, error wrapping, slog discipline, concurrency contract, table tests, no speculative abstractions) every package must satisfy to qualify as an exemplar. Verification section now distinguishes `make check` (continuous) from `make ci` (pre-PR). - CONTRIBUTING.md: dev quick-reference surfaces `make check`. Assisted-by: Anthropic:claude-opus-4-7 [Claude Code] Signed-off-by: Tri Lam --- AGENTS.md | 29 ++++++++++++++++-- CONTRIBUTING.md | 3 ++ Makefile | 10 +++++-- go.sum | 79 +++++++++++++++++++++++++++++++++---------------- 4 files changed, 91 insertions(+), 30 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index cb368d6f..8cbe2f75 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -57,12 +57,35 @@ AI tools are good at producing more code than is needed. When using one: - Don't add speculative abstractions, unused helpers, or "future-proofing" code. - Don't add comments that restate the code; STYLE.md requires comments only where the *why* is non-obvious. +## Exemplar packages + +When adding new code, find the closest existing analogue and copy its shape. Do not invent a new layout. Patterns expressed in code outlive prose, and a working example is faster to imitate than a rulebook to interpret. + +Canonical exemplars: + +- **Runtime / orchestration code**: `internal/pipeline/` — the pipeline runtime is the reference for package layout, doc comments, error wrapping, table-test style, and `Start`/`Shutdown` lifecycle. Lands with M1. +- **Components** (receivers, processors, exporters): the first stable component under `components///`. Until one ships, follow the layout rule in [`STYLE.md`](STYLE.md) §"Component layout" literally. + +Rubric — a package qualifies as an exemplar only when all of these hold. Apply this when reviewing M1; apply it when reviewing every package that lands after. + +- File layout matches [`STYLE.md`](STYLE.md) (§"Repo layout" or §"Component layout") with no deviations. +- Every exported identifier has a doc comment that explains *why* the caller should care, not what the code does. +- Errors use `fmt.Errorf("doing X: %w", err)`; no bare `return err` at boundaries; no `pkg/errors`, no `panic` outside `init()` / unrecoverable startup. +- Logging uses `*slog.Logger` passed via constructor — never package-global, never another library. +- Concurrency: every long-running goroutine takes a `context.Context` and exits on cancel; shutdown honours the 1s deadline from STYLE.md §"Concurrency". +- Tests are table-driven with `testify/require`; race-clean; deterministic (no time / network / disk dependencies in unit tests). +- No speculative abstractions, no unused exports, no comments that restate the code. +- `make check` is green and the package compiles in isolation (no hidden dependencies on `main`). + +If you have to bend the rubric to land code, say so explicitly in the PR and link the RFC or commit that justifies the deviation. Silent divergence is the failure mode this section exists to prevent. + ## Verification before submitting -Run locally before opening a PR: +Two commands, two audiences: ```sh -make ci +make check # fast inner loop: fmt, tidy-check, lint, test. Run while editing. +make ci # full pre-PR gate: license-check, vet, lint, test, build. Run before pushing. ``` -This runs license-check, `go vet`, `golangci-lint`, race-tested tests, and the build. If `make ci` does not pass, the PR will not pass either. +`make check` is what you should keep running every few minutes. `make ci` is what CI runs; if it doesn't pass locally, the PR won't pass either. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 774b7ba5..1d65d72b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -27,9 +27,12 @@ go mod download # one-time after clone make build # builds ./tracecore make test # unit tests with race detector make lint # runs golangci-lint +make check # fast inner loop: fmt + tidy-check + lint + test make ci # what CI runs: license-check + vet + lint + test + build ``` +Use `make check` continuously while editing; use `make ci` once before pushing. + ## Pull requests - **One concern per PR.** Don't mix refactors with feature work. Smaller PRs are easier to review — split when the diff outgrows the concern, not when it crosses an arbitrary line count. diff --git a/Makefile b/Makefile index 5b221f09..9f2ff6fd 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: help build run test fmt fmt-fix vet lint lint-fix tidy mod-verify license-check license-fix govulncheck dco-check ai-review clean ci +.PHONY: help build run test fmt fmt-fix vet lint lint-fix tidy tidy-check mod-verify license-check license-fix govulncheck dco-check ai-review clean check ci BIN := tracecore PKG := ./cmd/tracecore @@ -54,6 +54,10 @@ lint-fix: ## Run golangci-lint with --fix. tidy: ## Tidy go.mod / go.sum. go mod tidy +tidy-check: ## Verify go.mod / go.sum are tidy without mutating; fails with a diff if not. + @diff=$$(go mod tidy -diff 2>&1); \ + if [ -n "$$diff" ]; then echo "go.mod / go.sum need tidying:"; echo "$$diff"; exit 1; fi + mod-verify: ## Verify go.mod / go.sum hashes match (does not mutate; pair with `make tidy` to update). go mod verify @@ -73,7 +77,9 @@ license-fix: ## Add the SPDX header to any Go file missing it. govulncheck: ## Run govulncheck against the module. go tool govulncheck ./... -ci: license-check vet lint test build ## Everything CI runs. +check: fmt tidy-check lint test ## Fast inner-loop validation (no build, no license-check). Run continuously while editing. + +ci: license-check vet lint test build ## Everything CI runs. Run before opening a PR. dco-check: ## Verify DCO sign-off on every commit since origin/main. @if ! git rev-parse --verify --quiet origin/main >/dev/null; then \ diff --git a/go.sum b/go.sum index b6054a4d..dca298a9 100644 --- a/go.sum +++ b/go.sum @@ -57,12 +57,16 @@ github.com/Masterminds/semver/v3 v3.3.1 h1:QtNSWtVZ3nBfk8mAOu/B6v7FMJ+NHTIgUPi7r github.com/Masterminds/semver/v3 v3.3.1/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= github.com/OpenPeeDeeP/depguard/v2 v2.2.1 h1:vckeWVESWp6Qog7UZSARNqfu/cZqvki8zsuj3piCMx4= github.com/OpenPeeDeeP/depguard/v2 v2.2.1/go.mod h1:q4DKzC4UcVaAvcfd41CZh0PWpGgzrVxUYBlgKNGquUo= +github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0= +github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k= github.com/alecthomas/chroma/v2 v2.17.2 h1:Rm81SCZ2mPoH+Q8ZCc/9YvzPUN/E7HgPiPJD8SLV6GI= github.com/alecthomas/chroma/v2 v2.17.2/go.mod h1:RVX6AvYm4VfYe/zsk7mjHueLDZor3aWCNE14TFlepBk= github.com/alecthomas/go-check-sumtype v0.3.1 h1:u9aUvbGINJxLVXiFvHUlPEaD7VDULsrxJb4Aq31NLkU= github.com/alecthomas/go-check-sumtype v0.3.1/go.mod h1:A8TSiN3UPRw3laIgWEUOHHLPa6/r9MtoigdlP5h3K/E= github.com/alecthomas/kingpin/v2 v2.4.0 h1:f48lwail6p8zpO1bC4TxtqACaGqHYA22qkHjHpqDjYY= github.com/alecthomas/kingpin/v2 v2.4.0/go.mod h1:0gyi0zQnjuFk8xrkNKamJoyUo382HRL7ATRpFZCw6tE= +github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc= +github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -84,6 +88,8 @@ github.com/ashanbrown/makezero v1.2.0 h1:/2Lp1bypdmK9wDIq7uWBlDF1iMUpIIS4A+pF6C9 github.com/ashanbrown/makezero v1.2.0/go.mod h1:dxlPhHbDMC6N6xICzFBSK+4njQDdK8euNO0qjQMtGY4= github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= +github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= +github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -141,6 +147,8 @@ github.com/daixiang0/gci v0.13.6 h1:RKuEOSkGpSadkGbvZ6hJ4ddItT3cVZ9Vn9Rybk6xjl8= github.com/daixiang0/gci v0.13.6/go.mod h1:12etP2OniiIdP4q+kjUGrC/rUagga7ODbqsom5Eo5Yk= github.com/dave/dst v0.27.3 h1:P1HPoMza3cMEquVf9kKy8yXsFirry4zEnWOdYPOoIzY= github.com/dave/dst v0.27.3/go.mod h1:jHh6EOibnHgcUW3WjKHisiooEkYwqpHLBSX1iOBhEyc= +github.com/dave/jennifer v1.7.1 h1:B4jJJDHelWcDhlRQxWeo0Npa/pYKBLrirAQoTN45txo= +github.com/dave/jennifer v1.7.1/go.mod h1:nXbxhEmQfOZhWml3D1cDK5M1FLnMSozpbFN/m3RmGZc= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -160,6 +168,8 @@ github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4 github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94= github.com/firefart/nonamedreturns v1.0.6 h1:vmiBcKV/3EqKY3ZiPxCINmpS431OcE1S47AQUwhrg8E= github.com/firefart/nonamedreturns v1.0.6/go.mod h1:R8NisJnSIpvPWheCq0mNRXJok6D8h7fagJTF8EMEwCo= +github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= +github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps= github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= github.com/fzipp/gocyclo v0.6.0 h1:lsblElZG7d3ALtGMx9fmxeTKZaLLpU8mET09yN4BBLo= @@ -177,7 +187,13 @@ github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vb github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI= +github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= +github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/go-toolsmith/astcast v1.1.0 h1:+JN9xZV1A+Re+95pgnMgDboWNVnIMMQXwfBwLRPgSC8= github.com/go-toolsmith/astcast v1.1.0/go.mod h1:qdcuFWeGGS2xX5bLM/c3U9lewg7+Zu4mr+xPwZIB4ZU= github.com/go-toolsmith/astcopy v1.1.0 h1:YGwBN0WM+ekI/6SS6+52zLDEf8Yvp3n2seZITCUBt5s= @@ -190,6 +206,8 @@ github.com/go-toolsmith/astfmt v1.1.0 h1:iJVPDPp6/7AaeLJEruMsBUlOYCmvg0MoCfJprsO github.com/go-toolsmith/astfmt v1.1.0/go.mod h1:OrcLlRwu0CuiIBp/8b5PYF9ktGVZUjlNMV634mhwuQ4= github.com/go-toolsmith/astp v1.1.0 h1:dXPuCl6u2llURjdPLLDxJeZInAeZ0/eZwFJmqZMnpQA= github.com/go-toolsmith/astp v1.1.0/go.mod h1:0T1xFGz9hicKs8Z5MfAqSUitoUYS30pDMsRVIDHs8CA= +github.com/go-toolsmith/pkgload v1.2.2 h1:0CtmHq/02QhxcF7E9N5LIFcYFsMR5rdovfqTtRKkgIk= +github.com/go-toolsmith/pkgload v1.2.2/go.mod h1:R2hxLNRKuAsiXCo2i5J6ZQPhnPMOVtU+f0arbFPWCus= github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8= github.com/go-toolsmith/strparse v1.1.0 h1:GAioeZUK9TGxnLS+qfdqNbA4z0SSm5zVNtCQiyP2Bvw= github.com/go-toolsmith/strparse v1.1.0/go.mod h1:7ksGy58fsaQkGQlY8WVoBFNyEPMGuJin1rfoPS4lBSQ= @@ -255,6 +273,8 @@ github.com/google/addlicense v1.2.0 h1:W+DP4A639JGkcwBGMDvjSurZHvaq2FN0pP7se9czs github.com/google/addlicense v1.2.0/go.mod h1:Sm/DHu7Jk+T5miFHHehdIjbi4M5+dJDRS3Cq0rncIxA= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/go-cmdtest v0.4.1-0.20220921163831-55ab3332a786 h1:rcv+Ippz6RAtvaGgKxc+8FQIpxHgsF+HBzPyYL2cyVU= +github.com/google/go-cmdtest v0.4.1-0.20220921163831-55ab3332a786/go.mod h1:apVn/GCasLZUVpAJ6oWAuyP7Ne7CEsQbTnc0plM3m+o= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -267,8 +287,6 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -281,6 +299,9 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad h1:a6HEuzUHeKH6hwfN/ZoQgRgVIWFJljSWa/zetS2WTvg= +github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= +github.com/google/renameio v0.1.0 h1:GOZbcHa3HfsPKPlmyPyN2KEohoMXOhdMbHrvbpl2QaA= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= @@ -297,8 +318,12 @@ github.com/gostaticanalysis/forcetypeassert v0.2.0/go.mod h1:M5iPavzE9pPqWyeiVXS github.com/gostaticanalysis/nilerr v0.1.1 h1:ThE+hJP0fEp4zWLkWHWcRyI2Od0p7DlgYG3Uqrmrcpk= github.com/gostaticanalysis/nilerr v0.1.1/go.mod h1:wZYb6YI5YAxxq0i1+VJbY0s2YONW0HU0GPE3+5PWN4A= github.com/gostaticanalysis/testutil v0.3.1-0.20210208050101-bfb5c8eec0e4/go.mod h1:D+FIZ+7OahH3ePw/izIEeH5I06eKs1IKI4Xr64/Am3M= +github.com/gostaticanalysis/testutil v0.5.0 h1:Dq4wT1DdTwTGCQQv3rl3IvD5Ld0E6HiY+3Zh0sUGqw8= +github.com/gostaticanalysis/testutil v0.5.0/go.mod h1:OLQSbuM6zw2EvCcXTz1lVq5unyoNft372msDY0nY5Hs= github.com/hashicorp/go-immutable-radix/v2 v2.1.0 h1:CUW5RYIcysz+D3B+l1mDeXrQ7fUvGGCwJfdASSzbrfo= github.com/hashicorp/go-immutable-radix/v2 v2.1.0/go.mod h1:hgdqLXA4f6NIjRVisM1TJ9aOJVNRqKZj+xDGF6m7PBw= +github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= +github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-version v1.2.1/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= @@ -341,8 +366,12 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxv github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kulti/thelper v0.6.3 h1:ElhKf+AlItIu+xGnI990no4cE2+XaSu1ULymV2Yulxs= github.com/kulti/thelper v0.6.3/go.mod h1:DsqKShOvP40epevkFrvIwkCMNYxMeTNjdWL4dqWHZ6I= github.com/kunwardeep/paralleltest v1.0.14 h1:wAkMoMeGX/kGfhQBPODT/BL8XhK23ol/nuQ3SwFaUw8= @@ -375,6 +404,7 @@ github.com/maratori/testpackage v1.1.1 h1:S58XVV5AD7HADMmD0fNnziNHqKvSdDuEKdPD1r github.com/maratori/testpackage v1.1.1/go.mod h1:s4gRK/ym6AMrqpOa/kEbQTV4Q4jb7WeLZzVhVVVOQMc= github.com/matoous/godox v1.1.0 h1:W5mqwbyWrwZv6OQ5Z1a/DHGMOvXYCBP3+Ht7KMoJhq4= github.com/matoous/godox v1.1.0/go.mod h1:jgE/3fUXiTurkdHOLT5WEkThTSuE7yxHv5iWPa80afs= +github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE= github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= @@ -412,7 +442,13 @@ github.com/nunnatsa/ginkgolinter v0.19.1 h1:mjwbOlDQxZi9Cal+KfbEJTCz327OLNfwNvoZ github.com/nunnatsa/ginkgolinter v0.19.1/go.mod h1:jkQ3naZDmxaZMXPWaS9rblH+i+GWXQCaS/JFIWcOH2s= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= +github.com/onsi/ginkgo/v2 v2.23.3 h1:edHxnszytJ4lD9D5Jjc4tiDkPBZ3siDeJJkUZJJVkp0= +github.com/onsi/ginkgo/v2 v2.23.3/go.mod h1:zXTP6xIp3U8aVuXN8ENK9IXRaTjFnpVB9mGmaSRvxnM= +github.com/onsi/gomega v1.36.3 h1:hID7cr8t3Wp26+cYnfcjR6HpJ00fdogN6dqZ1t6IylU= +github.com/onsi/gomega v1.36.3/go.mod h1:8D9+Txp43QWKhM24yyOBEdpkzN8FvJyAwecBgsU4KU0= github.com/otiai10/copy v1.2.0/go.mod h1:rrF5dJ5F0t/EWSYODDu4j9/vEeYHMkc8jt0zJChqQWw= +github.com/otiai10/copy v1.14.0 h1:dCI/t1iTdYGtkvCuBG2BgR6KZa83PTclw4U5n2wAllU= +github.com/otiai10/copy v1.14.0/go.mod h1:ECfuL02W+/FkTWZWgQqXPWZgW9oeKCSQ5qVfSc4qc4w= github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs= github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= @@ -423,11 +459,14 @@ github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0 github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/polyfloyd/go-errorlint v1.8.0 h1:DL4RestQqRLr8U4LygLw8g2DX6RN1eBJOpa2mzsrl1Q= github.com/polyfloyd/go-errorlint v1.8.0/go.mod h1:G2W0Q5roxbLCt0ZQbdoxQxXktTjwNyDbEaj3n7jvl4s= +github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g= +github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= @@ -483,6 +522,8 @@ github.com/sashamelentyev/usestdlibvars v1.28.0 h1:jZnudE2zKCtYlGzLVreNp5pmCdOxX github.com/sashamelentyev/usestdlibvars v1.28.0/go.mod h1:9nl0jgOfHKWNFS43Ojw0i7aRoS4j6EBye3YBhmAIRF8= github.com/securego/gosec/v2 v2.22.3 h1:mRrCNmRF2NgZp4RJ8oJ6yPJ7G4x6OCiAXHd8x4trLRc= github.com/securego/gosec/v2 v2.22.3/go.mod h1:42M9Xs0v1WseinaB/BmNGO8AVqG8vRfhC2686ACY48k= +github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= +github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= @@ -526,8 +567,6 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5 github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= -github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= @@ -535,7 +574,9 @@ github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= github.com/tdakkota/asciicheck v0.4.1 h1:bm0tbcmi0jezRA2b5kg4ozmMuGAFotKI3RZfrhfovg8= github.com/tdakkota/asciicheck v0.4.1/go.mod h1:0k7M3rCfRXb0Z6bwgvkEIMleKH3kXNz9UqJ9Xuqopr8= +github.com/tenntenn/modver v1.0.1 h1:2klLppGhDgzJrScMpkj9Ujy3rXPUspSjAcev9tSEBgA= github.com/tenntenn/modver v1.0.1/go.mod h1:bePIyQPb7UeioSRkw3Q0XeMhYZSMx9B8ePqg6SAMGH0= +github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3 h1:f+jULpRQGxTSkNYKJ51yaw6ChIqO+Je8UqsTKN/cDag= github.com/tenntenn/text/transform v0.0.0-20200319021203-7eef512accb3/go.mod h1:ON8b8w4BN/kE1EOhwT0o+d62W65a6aPw1nouo9LMgyY= github.com/tetafro/godot v1.5.1 h1:PZnjCol4+FqaEzvZg5+O8IY2P3hfY9JzRBNPv1pEDS4= github.com/tetafro/godot v1.5.1/go.mod h1:cCdPtEndkmqqrhiCfkmxDodMQJ/f3L1BCNskCUZdTwk= @@ -576,6 +617,8 @@ github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1 github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= gitlab.com/bosi/decorder v0.4.2 h1:qbQaV3zgwnBZ4zPMhGLW4KZe7A7NwxEhJx39R3shffo= gitlab.com/bosi/decorder v0.4.2/go.mod h1:muuhHoaJkA9QLcYHq4Mj8FJUwDZ+EirSHRiaTcTf6T8= +go-simpler.org/assert v0.9.0 h1:PfpmcSvL7yAnWyChSjOz6Sp6m9j5lyK8Ok9pEL31YkQ= +go-simpler.org/assert v0.9.0/go.mod h1:74Eqh5eI6vCK6Y5l3PI8ZYFXG4Sa+tkr70OIPJAUr28= go-simpler.org/musttag v0.13.1 h1:lw2sJyu7S1X8lc8zWUAdH42y+afdcCnHhWpnkWvd6vU= go-simpler.org/musttag v0.13.1/go.mod h1:8r450ehpMLQgvpb6sg+hV5Ur47eH6olp/3yEanfG97k= go-simpler.org/sloglint v0.11.0 h1:JlR1X4jkbeaffiyjLtymeqmGDKBDO1ikC6rjiuFAOco= @@ -591,6 +634,8 @@ go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs= go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8= +go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= +go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= @@ -615,6 +660,7 @@ golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 h1:e66Fs6Z+fZTbFBAxKfP3PALWBtpfqks2bwGcexMxgtk= +golang.org/x/exp v0.0.0-20240909161429-701f63a606c0/go.mod h1:2TbTHSBQa924w8M6Xs1QcRcFwyucIwBGpK1p2f1YFFY= golang.org/x/exp/typeparams v0.0.0-20220428152302-39d4317da171/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= golang.org/x/exp/typeparams v0.0.0-20230203172020-98cc5a0785f9/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= golang.org/x/exp/typeparams v0.0.0-20250210185358-939b2ce775ac h1:TSSpLIG4v+p0rPv1pNOQtl1I8knsO4S9trOxNMOLVP4= @@ -648,10 +694,6 @@ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= -golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4= -golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU= golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -694,6 +736,8 @@ golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY= +golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -705,7 +749,6 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -716,10 +759,6 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= -golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= -golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= -golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610= golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -774,8 +813,6 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= -golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/telemetry v0.0.0-20240522233618-39ace7a40ae7 h1:FemxDzfMUcK2f3YY4H+05K9CDzbSVr2+q/JKN45pey0= @@ -861,18 +898,10 @@ golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= -golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc= -golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= -golang.org/x/tools v0.27.0 h1:qEKojBykQkQ4EynWy4S8Weg69NumxKdn40Fce3uc/8o= -golang.org/x/tools v0.27.0/go.mod h1:sUi0ZgbwW9ZPAq26Ekut+weQPR5eIM6GQLQ1Yjm1H0Q= -golang.org/x/tools v0.29.0 h1:Xx0h3TtM9rzQpQuR4dKLrdglAmCEN5Oi+P74JdhdzXE= -golang.org/x/tools v0.29.0/go.mod h1:KMQVMRsVxU6nHCFXrBPhDB8XncLNLM0lIy/F14RP588= golang.org/x/tools v0.32.0 h1:Q7N1vhpkQv7ybVzLFtTjvQya2ewbwNDZzUgfXGqtMWU= golang.org/x/tools v0.32.0/go.mod h1:ZxrU41P/wAbZD8EDa6dDCa6XfpkhJ7HFMjHJXfBDu8s= golang.org/x/vuln v1.1.3 h1:NPGnvPOTgnjBc9HTaUx+nj+EaUYxl5SJOWqaDYGaFYw= golang.org/x/vuln v1.1.3/go.mod h1:7Le6Fadm5FOqE9C926BCD0g12NWyhg7cxV4BwcPFuNY= -golang.org/x/vuln v1.1.4 h1:Ju8QsuyhX3Hk8ma3CesTbO8vfJD9EvUBgHvkxHBzj0I= -golang.org/x/vuln v1.1.4/go.mod h1:F+45wmU18ym/ca5PLTPLsSzr2KppzswxPP603ldA67s= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -958,6 +987,8 @@ gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLks gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= @@ -980,8 +1011,6 @@ honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9 honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= honnef.co/go/tools v0.6.1 h1:R094WgE8K4JirYjBaOpz/AvTyUu/3wbmAoskKN/pxTI= honnef.co/go/tools v0.6.1/go.mod h1:3puzxxljPCe8RGJX7BIy1plGbxEOZni5mR2aXe3/uk4= -mvdan.cc/gofumpt v0.7.0 h1:bg91ttqXmi9y2xawvkuMXyvAA/1ZGJqYAEGjXuP0JXU= -mvdan.cc/gofumpt v0.7.0/go.mod h1:txVFJy/Sc/mvaycET54pV8SW8gWxTlUuGHVEcncmNUo= mvdan.cc/gofumpt v0.8.0 h1:nZUCeC2ViFaerTcYKstMmfysj6uhQrA2vJe+2vwGU6k= mvdan.cc/gofumpt v0.8.0/go.mod h1:vEYnSzyGPmjvFkqJWtXkh79UwPWP9/HMxQdGEXZHjpg= mvdan.cc/unparam v0.0.0-20250301125049-0df0534333a4 h1:WjUu4yQoT5BHT1w8Zu56SP8367OuBV5jvo+4Ulppyf8= From 7355d780f5941ba7587461462201320805ec9698 Mon Sep 17 00:00:00 2001 From: Tri Lam Date: Wed, 13 May 2026 12:55:20 -0700 Subject: [PATCH 2/6] Address review on PR #10 and relax one-concern rule MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Five reinforcing tweaks surfaced by the line-by-line review: - AGENTS.md: rubric body becomes pointers into STYLE.md (Errors, Logging, Concurrency, Tests, Layout). STYLE.md is the source of truth; the rubric is now the checklist of which sections apply, not a restatement that drifts. Also: "Lands with M1" softened to "designated once M1 clears the rubric"; component path spelled out to match STYLE.md verbatim; "no hidden dependencies on main" reworded to "no reaching into cmd/tracecore globals"; "Two audiences" -> "Two cadences". - Makefile: tidy-check is now part of `ci`, not just `check`, so CI itself catches go.sum drift instead of relying on the contributor to remember the inner-loop command. - .github/workflows/pr-validation.yml: release-notes block skip pattern extended from docs/CI/tests to also cover Makefile, go.mod/go.sum, scripts/, .golangci.yml, .go-version, dotfiles — the paths with no user-visible runtime behavior. - CONTRIBUTING.md / AGENTS.md: "one concern per PR" rule relaxed to allow prerequisite cleanup that the change itself surfaces (e.g., a tidy-drift fix needed for a new gate to land green), provided it's called out in the PR body. This commit is itself such a case. - .claude/skills/fpr/SKILL.md: §9 expanded — when responding to review, also re-check the PR title and Summary/Changes sections against the current diff and rewrite them if scope shifted. Don't just append "Recent fixes" while the body stays stale. Assisted-by: Anthropic:claude-opus-4-7 [Claude Code] Signed-off-by: Tri Lam --- .claude/skills/fpr/SKILL.md | 22 +++++++++++++++++----- .github/workflows/pr-validation.yml | 18 +++++++++++++----- AGENTS.md | 26 +++++++++++++------------- CONTRIBUTING.md | 2 +- Makefile | 2 +- 5 files changed, 45 insertions(+), 25 deletions(-) diff --git a/.claude/skills/fpr/SKILL.md b/.claude/skills/fpr/SKILL.md index e741fe2b..6f0b3c77 100644 --- a/.claude/skills/fpr/SKILL.md +++ b/.claude/skills/fpr/SKILL.md @@ -159,13 +159,22 @@ mutation { Only resolve when the fix is clear and complete. For partial fixes or ongoing discussion, reply but don't resolve. -### 9. Update PR body +### 9. Update PR title and body + +The PR title and Summary / Changes sections describe the *final state* of the change, not the journey through review. After pushing fixes, re-check both against the current diff and update them if scope shifted. Appending a "Recent fixes" log is not a substitute for keeping the top-of-PR description accurate — reviewers and future readers read the body, not the commit list. ```bash -gh api repos/$REPO/pulls/ --jq '.body' > /tmp/pr_body.md +gh api repos/$REPO/pulls/ --jq '{title, body}' > /tmp/pr_state.json +gh pr diff > /tmp/pr_diff.patch ``` -Preserve all existing content (especially the PR template sections — Summary, Linked issues, Release notes, Checklist). Append a new section after the existing content: +Compare both against the current diff: + +- **Title** — if the PR now does something the title doesn't claim (or no longer does something it does claim), rewrite it. Keep ≤72 chars, imperative. +- **Summary / Changes / What changed** — edit these sections to match the current diff. Do *not* leave the original text and append "now also does X" — rewrite the affected section so it reads as if written after the latest push. +- **Test plan** — tick boxes that are now satisfied; add new items if scope grew during review. +- **Release notes block** — update if user-visible behavior changed; leave `NONE` if it didn't. +- **Recent fixes log** — append one bullet per addressed comment for the review audit trail: ```markdown @@ -176,11 +185,14 @@ Preserve all existing content (especially the PR template sections — Summary, - Responded: — replied without code change ``` -Then update: +Then write back. Preserve every section the template added (Summary, Linked issues, Release notes, Checklist, …). Never blank-overwrite; never strip sections you didn't intentionally rewrite. + ```bash -printf '%s' "$updated_body" | jq -Rs '{body: .}' | gh api repos/$REPO/pulls/ -X PATCH --input - +gh pr edit --title "" --body-file /tmp/pr_body.md ``` +If neither title nor body sections shifted, still append the "Recent fixes" log entry so the audit trail records this round. + ### 10. Summary report Print: diff --git a/.github/workflows/pr-validation.yml b/.github/workflows/pr-validation.yml index 55f6ccaa..a52db002 100644 --- a/.github/workflows/pr-validation.yml +++ b/.github/workflows/pr-validation.yml @@ -26,20 +26,28 @@ jobs: HEAD_SHA: ${{ github.event.pull_request.head.sha }} run: | set -euo pipefail - # Skip the check entirely when the PR only touches docs/CI/tests — - # those changes have no user-visible impact, so a release-notes - # block is theatre. Exiting 0 here marks the required check passing. + # Skip the check entirely when the PR only touches paths with no + # user-visible runtime behavior (docs, CI, build system, tooling + # pins). A release-notes block on those is theatre. Exiting 0 here + # marks the required check passing. mapfile -t changed < <(git diff --name-only "${BASE_SHA}" "${HEAD_SHA}") if [ "${#changed[@]}" -gt 0 ]; then skip=1 for f in "${changed[@]}"; do case "$f" in - *.md|docs/*|.github/*|tests/*) ;; + # Docs. + *.md|docs/*) ;; + # CI / governance. + .github/*) ;; + # Test fixtures and helper scripts. + tests/*|scripts/*) ;; + # Build system, tool pins, ignore files. + Makefile|go.mod|go.sum|.golangci.yml|.go-version|.gitignore|.gitattributes) ;; *) skip=0; break ;; esac done if [ "$skip" -eq 1 ]; then - echo "PR only touches docs/CI/tests — release-notes block check skipped." + echo "PR only touches docs/CI/build-tooling — release-notes block check skipped." exit 0 fi fi diff --git a/AGENTS.md b/AGENTS.md index 8cbe2f75..c68cf240 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -52,7 +52,7 @@ Do **not** use `Co-Authored-By:` for AI tools. That trailer is reserved for huma AI tools are good at producing more code than is needed. When using one: -- Keep PRs focused on one concern, per [`CONTRIBUTING.md`](CONTRIBUTING.md). Split when the diff outgrows the concern. +- Keep PRs focused on one concern, per [`CONTRIBUTING.md`](CONTRIBUTING.md). Split when the diff outgrows the concern. *Prerequisite cleanup the change itself surfaces* — e.g., a tidy-drift fix needed for a new gate to land green — can ride along if it's called out in the PR body. - Don't refactor unrelated code in the same PR. - Don't add speculative abstractions, unused helpers, or "future-proofing" code. - Don't add comments that restate the code; STYLE.md requires comments only where the *why* is non-obvious. @@ -63,25 +63,25 @@ When adding new code, find the closest existing analogue and copy its shape. Do Canonical exemplars: -- **Runtime / orchestration code**: `internal/pipeline/` — the pipeline runtime is the reference for package layout, doc comments, error wrapping, table-test style, and `Start`/`Shutdown` lifecycle. Lands with M1. -- **Components** (receivers, processors, exporters): the first stable component under `components///`. Until one ships, follow the layout rule in [`STYLE.md`](STYLE.md) §"Component layout" literally. +- **Runtime / orchestration code**: `internal/pipeline/` — will be designated as the reference for runtime package layout once M1 lands and clears the rubric below. +- **Components** (receivers, processors, exporters): the first stable component under `components/receivers//`, `components/processors//`, or `components/exporters//`. Until one ships, follow the layout rule in [`STYLE.md`](STYLE.md) §"Component layout" literally. -Rubric — a package qualifies as an exemplar only when all of these hold. Apply this when reviewing M1; apply it when reviewing every package that lands after. +Rubric — a package qualifies as an exemplar only when every item below holds. STYLE.md is the source of truth; this list is the review checklist for which sections apply, not a restatement. -- File layout matches [`STYLE.md`](STYLE.md) (§"Repo layout" or §"Component layout") with no deviations. -- Every exported identifier has a doc comment that explains *why* the caller should care, not what the code does. -- Errors use `fmt.Errorf("doing X: %w", err)`; no bare `return err` at boundaries; no `pkg/errors`, no `panic` outside `init()` / unrecoverable startup. -- Logging uses `*slog.Logger` passed via constructor — never package-global, never another library. -- Concurrency: every long-running goroutine takes a `context.Context` and exits on cancel; shutdown honours the 1s deadline from STYLE.md §"Concurrency". -- Tests are table-driven with `testify/require`; race-clean; deterministic (no time / network / disk dependencies in unit tests). -- No speculative abstractions, no unused exports, no comments that restate the code. -- `make check` is green and the package compiles in isolation (no hidden dependencies on `main`). +- **Layout** — matches [`STYLE.md`](STYLE.md) §"Repo layout" / §"Component layout" with no deviations. +- **Errors** — follows [`STYLE.md`](STYLE.md) §"Error handling". +- **Logging** — follows [`STYLE.md`](STYLE.md) §"Logging". +- **Concurrency / lifecycle** — follows [`STYLE.md`](STYLE.md) §"Concurrency". +- **Tests** — follows [`STYLE.md`](STYLE.md) §"Testing". +- **Doc comments** — every exported identifier explains *why* a caller should care, not what the code does. +- **Scope** — no speculative abstractions, no unused exports, no comments that restate the code (see §"Scope discipline" above). +- **Green** — `make check` passes; the package compiles without reaching into `cmd/tracecore` globals. If you have to bend the rubric to land code, say so explicitly in the PR and link the RFC or commit that justifies the deviation. Silent divergence is the failure mode this section exists to prevent. ## Verification before submitting -Two commands, two audiences: +Two commands, two cadences: ```sh make check # fast inner loop: fmt, tidy-check, lint, test. Run while editing. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1d65d72b..288d8bae 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -35,7 +35,7 @@ Use `make check` continuously while editing; use `make ci` once before pushing. ## Pull requests -- **One concern per PR.** Don't mix refactors with feature work. Smaller PRs are easier to review — split when the diff outgrows the concern, not when it crosses an arbitrary line count. +- **One concern per PR — with room for prerequisites.** Don't mix unrelated refactors with feature work. Smaller PRs are easier to review — split when the diff outgrows the concern, not when it crosses an arbitrary line count. *Prerequisite cleanup that the change itself surfaces* (e.g., a tidy-drift fix needed for a new gate to land green) can ride along when it's called out in the commit body and PR description. - **Tests required** for new functionality. Bug fixes should include a regression test. - **Atomic commits.** Each commit must build and pass tests on its own. - **Sign off your commits**: `git commit -s`. We require [DCO](https://developercertificate.org/). diff --git a/Makefile b/Makefile index 9f2ff6fd..6781e9a1 100644 --- a/Makefile +++ b/Makefile @@ -79,7 +79,7 @@ govulncheck: ## Run govulncheck against the module. check: fmt tidy-check lint test ## Fast inner-loop validation (no build, no license-check). Run continuously while editing. -ci: license-check vet lint test build ## Everything CI runs. Run before opening a PR. +ci: license-check vet lint tidy-check test build ## Everything CI runs. Run before opening a PR. dco-check: ## Verify DCO sign-off on every commit since origin/main. @if ! git rev-parse --verify --quiet origin/main >/dev/null; then \ From 8d18ba114f8c45a0a766a53114d76dce20bbb404 Mon Sep 17 00:00:00 2001 From: Tri Lam Date: Wed, 13 May 2026 13:09:47 -0700 Subject: [PATCH 3/6] Fix tidy-check: capture stdout only, not stderr chatter `go mod tidy -diff` writes the actual diff to stdout, but in fresh environments (CI on a clean checkout) it also writes "go: downloading X" messages to stderr while fetching the module info it needs to compute the diff. Capturing both with `2>&1` made the variable non-empty whenever any download chatter appeared, which falsely failed the check on CI even when go.mod / go.sum were perfectly tidy. Locally the module cache silenced stderr, so the bug was invisible. Caught by CI's `verify` job on this same PR after `tidy-check` was added to the `ci` target. Drop the `2>&1` so only stdout (the real diff) decides pass/fail; let stderr flow to the terminal for visibility but not into the decision. Assisted-by: Anthropic:claude-opus-4-7 [Claude Code] Signed-off-by: Tri Lam --- Makefile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 6781e9a1..39226e7a 100644 --- a/Makefile +++ b/Makefile @@ -55,7 +55,10 @@ tidy: ## Tidy go.mod / go.sum. go mod tidy tidy-check: ## Verify go.mod / go.sum are tidy without mutating; fails with a diff if not. - @diff=$$(go mod tidy -diff 2>&1); \ + @# Capture stdout only — `go mod tidy -diff` writes the actual diff to + @# stdout, but emits "go: downloading X" chatter to stderr in fresh + @# environments (CI). Slurping both with `2>&1` falsely fails the check. + @diff=$$(go mod tidy -diff); \ if [ -n "$$diff" ]; then echo "go.mod / go.sum need tidying:"; echo "$$diff"; exit 1; fi mod-verify: ## Verify go.mod / go.sum hashes match (does not mutate; pair with `make tidy` to update). From b0fac1f7964f3ff146c678f819ba7b9a73c335f4 Mon Sep 17 00:00:00 2001 From: Tri Lam Date: Wed, 13 May 2026 13:07:24 -0700 Subject: [PATCH 4/6] Add developer foundation: hooks, issue templates, editorconfig MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Four small, durable additions that compound for the life of the project, bundled per the relaxed one-concern-with-prerequisites rule: - .githooks/pre-commit + `make hooks` target: opt-in pre-commit hook that runs `make check` on every commit. Installation is one command (`make hooks` sets core.hooksPath to .githooks). Bypass with --no-verify; CI still catches what gets skipped. Encodes the inner loop as a default, not a discipline contributors have to remember. - .github/ISSUE_TEMPLATE/{bug_report.md,feature_request.md,config.yml}: structured bug and feature templates. config.yml disables blank issues and routes architectural changes to docs/rfcs/, security reports to private advisories, and questions to Discussions. Makes the first external issue the *least* badly-formatted instead of the most. - .editorconfig: charset, EOL, indent rules for Go (tabs), Makefile (tabs), go.mod/go.sum (tabs), Markdown (preserve trailing whitespace for hard breaks), everything else (2 spaces). Locks down decisions gofumpt doesn't cover so YAML/Markdown contributors don't accidentally drift. - .github/PULL_REQUEST_TEMPLATE.md polish: drops the "Keep PRs under 500 lines" line that contradicts the just-relaxed one-concern rule; adds `make check` to the checklist alongside `make ci`; adds the "PR title and Summary still reflect the current diff" item that the /fpr skill §9 now enforces. - CONTRIBUTING.md: dev quick-reference surfaces `make hooks`. Depends on PR #10 (the pre-commit hook calls `make check`, which #10 introduces). Diff will collapse once #10 merges. Assisted-by: Anthropic:claude-opus-4-7 [Claude Code] Signed-off-by: Tri Lam --- .editorconfig | 21 ++++++++ .githooks/pre-commit | 6 +++ .github/ISSUE_TEMPLATE/bug_report.md | 58 +++++++++++++++++++++++ .github/ISSUE_TEMPLATE/config.yml | 11 +++++ .github/ISSUE_TEMPLATE/feature_request.md | 48 +++++++++++++++++++ .github/PULL_REQUEST_TEMPLATE.md | 8 +++- CONTRIBUTING.md | 3 +- Makefile | 7 ++- 8 files changed, 158 insertions(+), 4 deletions(-) create mode 100644 .editorconfig create mode 100755 .githooks/pre-commit create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/config.yml create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..71666083 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,21 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true +indent_style = space +indent_size = 2 + +[*.go] +indent_style = tab + +[Makefile] +indent_style = tab + +[{go.mod,go.sum}] +indent_style = tab + +[*.{md,markdown}] +trim_trailing_whitespace = false diff --git a/.githooks/pre-commit b/.githooks/pre-commit new file mode 100755 index 00000000..e28b0af6 --- /dev/null +++ b/.githooks/pre-commit @@ -0,0 +1,6 @@ +#!/usr/bin/env bash +# Pre-commit hook: run `make check` to keep the inner loop honest. +# Installed by `make hooks`, which sets core.hooksPath to .githooks. +# Bypass with `git commit --no-verify` if you must — CI will still catch you. +set -euo pipefail +exec make check diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 00000000..f75f2c8a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,58 @@ +--- +name: Bug report +about: Report something that isn't working +title: '' +labels: bug +--- + + + +## What happened + + + +## What you expected + + + +## Reproduction + + + +```yaml +# minimal config here +``` + +```sh +# commands here +``` + +## Environment + +- tracecore version (`tracecore --version`): +- OS / kernel: +- Go version (`go version`) — only if building from source: +- GPU / driver / NCCL versions — only if relevant to the bug: + +## Logs + + + +``` +logs here +``` + +## Additional context + + diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 00000000..2c0b74cc --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,11 @@ +blank_issues_enabled: false +contact_links: + - name: Architectural proposal (RFC) + url: https://github.com/TraceCoreAI/tracecore/blob/main/docs/rfcs/0000-template.md + about: Architectural decisions go through the RFC process. Copy the template into docs/rfcs/ and open a PR — not an issue. + - name: Security vulnerability + url: https://github.com/TraceCoreAI/tracecore/security/advisories/new + about: Report vulnerabilities privately, never as public issues. See SECURITY.md. + - name: Question or discussion + url: https://github.com/TraceCoreAI/tracecore/discussions + about: For open-ended questions and design discussion. Bugs and feature requests belong in issues. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 00000000..149b9488 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,48 @@ +--- +name: Feature request +about: Suggest a new feature or enhancement +title: '' +labels: enhancement +--- + + + +## Problem + + + +## Proposal + + + +## Alternatives considered + + + +## Out of scope + + + +## Additional context + + diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index eaac3f29..0a56fb40 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,6 +1,9 @@ ## What this PR does @@ -28,7 +31,8 @@ Categories: FEATURE, ENHANCEMENT, BUGFIX, PERF, SECURITY, CHANGE ## Checklist - [ ] Tests added or updated -- [ ] `make ci` passes locally +- [ ] `make check` runs green continuously while editing; `make ci` passes before pushing - [ ] Commits are signed off (`git commit -s`) - [ ] If AI-assisted, commit message includes `Assisted-by:` trailer (see [`AGENTS.md`](../AGENTS.md)) - [ ] For new components, follows the layout required by [`STYLE.md`](../STYLE.md) +- [ ] PR title and Summary still reflect the current diff (re-check after pushing fixes) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 288d8bae..5b121b7d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -24,6 +24,7 @@ All developer tools (gofumpt, goimports, golangci-lint, govulncheck, addlicense) ```sh go mod download # one-time after clone +make hooks # one-time: install pre-commit hook that runs `make check` make build # builds ./tracecore make test # unit tests with race detector make lint # runs golangci-lint @@ -31,7 +32,7 @@ make check # fast inner loop: fmt + tidy-check + lint + test make ci # what CI runs: license-check + vet + lint + test + build ``` -Use `make check` continuously while editing; use `make ci` once before pushing. +Use `make check` continuously while editing; use `make ci` once before pushing. `make hooks` is opt-in but recommended — it installs `.githooks/pre-commit` so `make check` runs automatically on every `git commit`. Bypass with `git commit --no-verify` if you must; CI still catches what you skip. ## Pull requests diff --git a/Makefile b/Makefile index 39226e7a..c9c3470f 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: help build run test fmt fmt-fix vet lint lint-fix tidy tidy-check mod-verify license-check license-fix govulncheck dco-check ai-review clean check ci +.PHONY: help build run test fmt fmt-fix vet lint lint-fix tidy tidy-check mod-verify license-check license-fix govulncheck dco-check ai-review hooks clean check ci BIN := tracecore PKG := ./cmd/tracecore @@ -93,6 +93,11 @@ dco-check: ## Verify DCO sign-off on every commit since origin/main. ai-review: ## Run advisory Claude review on staged Go changes (never blocks). @scripts/ai-review.sh +hooks: ## Install repo-managed Git hooks (sets core.hooksPath to .githooks). + @git config core.hooksPath .githooks + @echo "Hooks installed. .githooks/pre-commit will run \`make check\` on every commit." + @echo "Bypass once with: git commit --no-verify" + clean: ## Remove built binaries. rm -f $(BIN) go clean From eb1b170cdd0f4636d94b9a1fe6d3c836028f5cc7 Mon Sep 17 00:00:00 2001 From: Tri Lam Date: Wed, 13 May 2026 13:16:20 -0700 Subject: [PATCH 5/6] Add commit-msg + pre-push hooks and setup-dev script MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Round out the .githooks/ suite introduced earlier in this PR so the moment of truth for whether a change passes is `git push`, not the CI queue. Three complementary gates: - .githooks/commit-msg: enforces the two rules CI checks per-commit — ≤72-char subject (STYLE.md §Commits) and DCO Signed-off-by trailer (matches .github/scripts/dco-check.sh). Skips git-managed shapes (Merge, fixup!, squash!, amend!) where the rules don't apply. Catches the exact failure mode this branch hit twice today: forgetting -s. - .githooks/pre-push: runs `make ci` so the full gate (license, vet, lint, tidy, test with race, build) fires before the network round-trip. Closes the gap between pre-commit's lighter `make check` and CI's full sweep, which is the gap that surfaced this PR's tidy-check stderr bug (caught only after pushing). - scripts/setup-dev.sh: idempotent one-shot bootstrap — runs `go mod download` and `make hooks`, then prints the hook map. Replaces the two-step manual setup in CONTRIBUTING.md with one command, while `make hooks` stays available for users who already downloaded modules. - CONTRIBUTING.md: dev quick-reference now points at setup-dev.sh and documents the three hooks together. All three hooks honour `--no-verify` for emergencies. CI remains the final authority; locally enforced is a velocity multiplier, not a gate. Assisted-by: Anthropic:claude-opus-4-7 [Claude Code] Signed-off-by: Tri Lam --- .githooks/commit-msg | 36 ++++++++++++++++++++++++++++++++++++ .githooks/pre-push | 7 +++++++ CONTRIBUTING.md | 13 +++++++++---- scripts/setup-dev.sh | 25 +++++++++++++++++++++++++ 4 files changed, 77 insertions(+), 4 deletions(-) create mode 100755 .githooks/commit-msg create mode 100755 .githooks/pre-push create mode 100755 scripts/setup-dev.sh diff --git a/.githooks/commit-msg b/.githooks/commit-msg new file mode 100755 index 00000000..c80a92f1 --- /dev/null +++ b/.githooks/commit-msg @@ -0,0 +1,36 @@ +#!/usr/bin/env bash +# commit-msg hook: enforce DCO sign-off and ≤72-char subject locally so we +# don't burn a CI cycle (or push, see the maintainer's mood drop) discovering +# either after the fact. Skips git-managed commit shapes (Merge, fixup!, +# squash!, amend!) where the rules don't apply or git rewrites the message. +# Bypass with `git commit --no-verify` if you must — CI still checks. +set -euo pipefail + +msg_file="$1" +[ -f "$msg_file" ] || exit 0 + +# First non-comment line is the subject (`git commit -v` prepends comments). +subject=$(grep -v '^#' "$msg_file" | head -n 1) + +case "$subject" in + Merge*|fixup!*|squash!*|amend!*) exit 0 ;; +esac + +# Subject length — see STYLE.md §"Commits". +subject_len=${#subject} +if [ "$subject_len" -gt 72 ]; then + echo "ERROR: commit subject is $subject_len chars (limit: 72)." >&2 + echo " Subject: $subject" >&2 + echo " Trim the subject; put detail in the body." >&2 + exit 1 +fi + +# DCO sign-off — matches .github/scripts/dco-check.sh which gates CI. +if ! grep -q '^Signed-off-by: ' "$msg_file"; then + echo "ERROR: missing Signed-off-by trailer." >&2 + echo " Use 'git commit -s' to add it, or amend with --signoff." >&2 + echo " See CONTRIBUTING.md §'Sign off your commits'." >&2 + exit 1 +fi + +exit 0 diff --git a/.githooks/pre-push b/.githooks/pre-push new file mode 100755 index 00000000..34b464fd --- /dev/null +++ b/.githooks/pre-push @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +# pre-push hook: run `make ci` so the moment of truth is `git push`, not the +# wait for GitHub Actions. Catches what `make check` (the pre-commit gate) +# deliberately skips: license-check, full build, govulncheck-adjacent checks. +# Bypass with `git push --no-verify` if you must — CI will still catch you. +set -euo pipefail +exec make ci diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5b121b7d..98085d66 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -23,16 +23,21 @@ When you choose to file one: All developer tools (gofumpt, goimports, golangci-lint, govulncheck, addlicense) are pinned in `go.mod` under the `tool` directive and fetched automatically. There is no separate `install-tools` step. ```sh -go mod download # one-time after clone -make hooks # one-time: install pre-commit hook that runs `make check` +scripts/setup-dev.sh # one-shot: go mod download + install all hooks make build # builds ./tracecore make test # unit tests with race detector make lint # runs golangci-lint make check # fast inner loop: fmt + tidy-check + lint + test -make ci # what CI runs: license-check + vet + lint + test + build +make ci # what CI runs: license-check + vet + lint + tidy + test + build ``` -Use `make check` continuously while editing; use `make ci` once before pushing. `make hooks` is opt-in but recommended — it installs `.githooks/pre-commit` so `make check` runs automatically on every `git commit`. Bypass with `git commit --no-verify` if you must; CI still catches what you skip. +`scripts/setup-dev.sh` is idempotent — rerun it whenever. It installs three hooks (opt-in via `core.hooksPath = .githooks`) so problems surface before they hit CI: + +- **`pre-commit`** runs `make check` — fmt, tidy, lint, race-tested tests. +- **`commit-msg`** enforces the ≤72-char subject and DCO sign-off rules from STYLE.md §"Commits". +- **`pre-push`** runs `make ci` — the full gate CI runs, locally, before the network round-trip. + +Bypass any hook with `--no-verify` if you must (`git commit --no-verify`, `git push --no-verify`); CI still catches what you skip. ## Pull requests diff --git a/scripts/setup-dev.sh b/scripts/setup-dev.sh new file mode 100755 index 00000000..b74ed27d --- /dev/null +++ b/scripts/setup-dev.sh @@ -0,0 +1,25 @@ +#!/usr/bin/env bash +# One-shot dev environment bootstrap. Run after cloning. Idempotent — +# rerunning is safe and only re-applies what changed. +set -euo pipefail + +cd "$(git rev-parse --show-toplevel)" + +echo "==> Downloading Go modules and tools..." +go mod download + +echo "==> Installing Git hooks..." +make hooks + +cat <<'EOF' + +Setup complete. The hooks now run automatically: + pre-commit -> make check (fmt, tidy-check, lint, test) + commit-msg -> DCO sign-off + subject length + pre-push -> make ci (license, vet, lint, tidy, test, build) + +Manual commands you'll still want: + make check fast inner loop (~10s) + make ci full pre-push gate (~30s) + make help every target with one-line docs +EOF From 96ca680fc41a38958d80ba141c8b67cabc274bd1 Mon Sep 17 00:00:00 2001 From: Tri Lam Date: Wed, 13 May 2026 13:27:03 -0700 Subject: [PATCH 6/6] Polish PR #11 per second-pass review Five small tightenings: - Makefile: `make hooks` output now lists all three hooks (was stale, only mentioned pre-commit). Anyone running `make hooks` directly (not through setup-dev.sh) gets an accurate picture. - scripts/setup-dev.sh: pre-flight check for `go` on PATH so the failure mode is a clear error message with install pointer, not a confusing `go: command not found` from `go mod download`. Also trimmed the "Downloading Go modules and tools" message to just "modules" since tools are pulled on-demand by `go tool`, not by `go mod download`. - .githooks/commit-msg: clarified that the DCO check mirrors .github/scripts/dco-check.sh and notes future drift risk. - .github/PULL_REQUEST_TEMPLATE.md: replaced the bare "Fixes #" placeholder (which rendered verbatim if a contributor forgot to edit it) with an explicit "_No linked issue._" default and clearer instructions to either replace or delete the section. Assisted-by: Anthropic:claude-opus-4-7 [Claude Code] Signed-off-by: Tri Lam --- .githooks/commit-msg | 3 ++- .github/PULL_REQUEST_TEMPLATE.md | 8 ++++++-- Makefile | 7 +++++-- scripts/setup-dev.sh | 10 +++++++++- 4 files changed, 22 insertions(+), 6 deletions(-) diff --git a/.githooks/commit-msg b/.githooks/commit-msg index c80a92f1..28cc78cb 100755 --- a/.githooks/commit-msg +++ b/.githooks/commit-msg @@ -25,7 +25,8 @@ if [ "$subject_len" -gt 72 ]; then exit 1 fi -# DCO sign-off — matches .github/scripts/dco-check.sh which gates CI. +# DCO sign-off — mirrors the rules enforced by .github/scripts/dco-check.sh +# (the CI gate). Keep this check in sync if that script changes. if ! grep -q '^Signed-off-by: ' "$msg_file"; then echo "ERROR: missing Signed-off-by trailer." >&2 echo " Use 'git commit -s' to add it, or amend with --signoff." >&2 diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 0a56fb40..242863a3 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -12,9 +12,13 @@ land green) can ride along when called out in the PR body. ## Linked issue(s) - + -Fixes # +_No linked issue._ ## Release notes diff --git a/Makefile b/Makefile index c9c3470f..015210ec 100644 --- a/Makefile +++ b/Makefile @@ -95,8 +95,11 @@ ai-review: ## Run advisory Claude review on staged Go changes (never blocks). hooks: ## Install repo-managed Git hooks (sets core.hooksPath to .githooks). @git config core.hooksPath .githooks - @echo "Hooks installed. .githooks/pre-commit will run \`make check\` on every commit." - @echo "Bypass once with: git commit --no-verify" + @echo "Hooks installed under .githooks/ — all three now active:" + @echo " pre-commit -> make check (fmt, tidy-check, lint, test)" + @echo " commit-msg -> ≤72-char subject + DCO sign-off" + @echo " pre-push -> make ci (full gate)" + @echo "Bypass any one with --no-verify; CI still catches what you skip." clean: ## Remove built binaries. rm -f $(BIN) diff --git a/scripts/setup-dev.sh b/scripts/setup-dev.sh index b74ed27d..aa7d2b60 100755 --- a/scripts/setup-dev.sh +++ b/scripts/setup-dev.sh @@ -5,7 +5,15 @@ set -euo pipefail cd "$(git rev-parse --show-toplevel)" -echo "==> Downloading Go modules and tools..." +if ! command -v go >/dev/null 2>&1; then + required=$(cat .go-version 2>/dev/null || echo "see .go-version") + echo "ERROR: Go is not installed or not on PATH." >&2 + echo " Required version: $required" >&2 + echo " Install from https://go.dev/dl/ or via your package manager." >&2 + exit 1 +fi + +echo "==> Downloading Go modules..." go mod download echo "==> Installing Git hooks..."