Thanks for thinking about contributing. This document captures the repo-specific build, test, and lint flow. The org-wide CONTRIBUTING guide covers licensing (inbound = outbound, GPL-3.0-or-later), Conventional Commits, PR conventions, and how to file issues — that document applies here too.
- Go 1.25+ — lower versions will not compile.
golangci-lintv1.55+ formake lint.goimportsformake fmt(go install golang.org/x/tools/cmd/goimports@latest).bashfor the helper scripts. On Windows use Git Bash or WSL.- Optional:
goreleaserv2 for local release dry-runs.
make build # → ./commitbrief
make test # unit + integration; live provider tests excluded
make lint # golangci-lint
make fmt # gofmt + goimports
make tidy # go mod tidyRun a single test:
go test ./internal/<pkg> -run TestName -vLive provider tests (real API keys required) are gated behind a build tag:
make test-live # = go test -tags=live ./...PRD §7.1 sets four ceilings for local-only work (no network):
| Target | Ceiling | Where it lives |
|---|---|---|
Cold start (commitbrief --version) |
< 100 ms | binary startup |
| Local pipeline on a 10k-line diff (parse + filter + token estimate) | < 200 ms | internal/diff |
dry-run total wall time |
< 500 ms | internal/cli (integration) |
| Cache hit additional latency | < 100 ms | internal/cache |
The two component targets are exercised by make bench
(internal/diff/bench_test.go, internal/cache/bench_test.go).
Cold start is a binary-startup measurement, not a Go benchmark; time
it on a release build with the shell builtin (see below). The
dry-run target is integration-level — time it end-to-end after a
real git init + staged change.
# Component benchmarks (parse + filter + token estimate + cache hit):
make bench
# Cold start (steady state — discard the first run, it includes
# macOS Gatekeeper / unsigned-binary verification ~600 ms on a
# `go build` artifact; brew-installed binaries are verified once at
# install time):
make build
for i in 1 2 3 4 5; do { time ./commitbrief --version >/dev/null; } 2>&1 | tail -1; done
# dry-run wall time (against a real staged change):
time commitbrief dry-run --stagedReference numbers on darwin/arm64 (Apple M4 Pro), Go 1.25.6, v0.6.0-pre. Update the table when you bump targets, change algorithms, or add a new layer to the pipeline:
| Benchmark | ns/op | ms/op | vs PRD target |
|---|---|---|---|
Parse10kLines |
656,745 | 0.66 | — (component) |
Filter10kLines |
1,931,639 | 1.93 | — (component) |
EstimateTokens10kLines |
11,052 | 0.011 | — (component) |
Pipeline10kLines (headline) |
2,602,795 | 2.60 | < 200 ms ✅ (~75× headroom) |
CacheHit |
12,764 | 0.013 | < 100 ms ✅ (~7700× headroom) |
| Cold start (steady) | — | ~16 | < 100 ms ✅ (~6× headroom) |
Hot-path watch-outs that have eaten margin in the past:
bufio.Scannerbuffer ininternal/diff/parse.gois sized to 16 MiB to tolerate a single huge hunk. Shrinking this hits very-large diffs hard; do not lower without measurement.go-git's gitignore matcher is allocation-heavy on initial pattern compile but cheap per match;ignore.Composedoes the compile once perFilter()call. Per-file matching is the bulk ofFilter10kLines.
If a benchmark in this table regresses by >20% in a PR, mention it explicitly in the description with a justification (a clearer implementation that costs a few ns may still be net-positive).
cmd/commitbrief/— thin entry point.internal/— every package; nopkg/in v1 — there is no stable public Go API.testdata/— fixture repos, diff samples, ignore patterns, golden files.scripts/— release-check, license-check, manpage generation.
make fmt lint testis green locally.- New user-facing strings go through
internal/i18n; add the key to bothmessages.en.ymlandmessages.tr.yml. - Material decisions or scope changes update the appropriate ADR (open a new ADR if needed — supersede rather than silently contradict an existing one).
- New dependencies follow the Adding a dependency
checklist and pass
make license-check. - Pre-release tags additionally pass
make release-check(e.g. theinternal/rules/default.mdplaceholder guard from PRD §10 / OQ-25).
The fastest way to clear gates 1, 2, and 4 (plus the SPDX-header and
i18n parity checks) in one shot is make check — the same gate CI runs.
New third-party modules are accepted but deliberately rare. Every import becomes combined work under GPL-3.0 (the conservative reading for statically-linked Go), adds supply-chain surface, and grows the binary. Before adding one, work through this checklist:
- Justify it. Can the standard library or an already-required module
do the job? For a new LLM provider specifically, prefer reusing the
existing
openai-goclient against the provider's OpenAI-compatible endpoint — thedeepseek/mistral/coherepackages do exactly this and add zero new dependencies — before pulling in a bespoke SDK. - Check the license. It must be on the GPL-3.0-compatible allow-list
maintained in
scripts/license-check.sh:Apache-2.0,BSD-2-Clause,BSD-3-Clause,GPL-3.0(-or-later),ISC,LGPL-3.0(-or-later),MIT,MPL-2.0,Unlicense. AGPL, proprietary, and anything not on the list are rejected — no exceptions. Check the module's own license and its transitive dependencies. - Add and sync.
go get <module>@<version>, thenmake tidysogo.mod/go.sumstay clean and minimal. Pin a specific released version, not a branch or pseudo-version, unless there is no tagged release. - Audit.
make license-checkmust pass locally — it runsgo-licensesover the entire module graph (transitive deps included), not just your direct addition. CI enforces it too. - If it's incompatible, don't vendor it. When a module you want ships under an incompatible license, build the integration in-house or find a compatible replacement rather than adding it.
- Document. State the new dependency and why in the PR description.
If it changes user-facing behavior, add a
CHANGELOG.mdentry.
CommitBrief targets macOS, Linux, and Windows on amd64 and arm64 from a
single codebase: always use path/filepath, normalize ignore patterns with
filepath.ToSlash, prefer os.UserHomeDir / os.UserConfigDir. Platform
splits use //go:build tags (*_windows.go / *_unix.go).
Use the bug-report and feature-request templates inherited from the org
.github repository. For "how do I…" questions, open a Discussion in
this repo. Security issues go through
SECURITY.md
privately — do not open public issues for vulnerabilities.
Off-channel email: info@muhammetsafak.com.tr.