- Treat this AGENTS.md as the single source that distills historical reviewers’ expectations. Use it for every AI review, test run, and documentation update.
- Keep these rules up-to-date: add patterns when they become common, update standards as they evolve, and remove outdated guidance. The agent tooling applies this file automatically, so changes here matter.
- Expect Go services to include API layers, background workers, persistence stacks, and optional crypto/math helpers. Prefer
go-chi/corsfor routing,zerolog/logfor structured logs,viper/pflagfor config, zk tooling (gnark,gnark-crypto) for proof work,go-ethereumfor chain plumbing,pebble/goleveldbfor storage, and AWS SDK v2 when interacting with cloud artifacts. - Keep packages focused per responsibility, design modular interfaces, and configure behavior through environment variables instead of hard-coded constants.
- Always run
gofmtbefore submitting changes; let the formatter handle indentation and alignment. - Use structured logging (
log.Debugw,log.Errorw,log.Infow) with contextual fields (IDs, durations, counts); prefer these overfmt.Printf. - Create errors via
fmt.Errorf(noterrors.New) so%wwrapping is always possible. Wrap every caller with context (fmt.Errorf("fetch user: %w", err)) and include the operation name. - Use
bytes.Equalor direct array comparisons for slices, and avoid conversions (e.g.,common.BytesToAddress) unless you truly need the struct. - Favor early returns, drop redundant
elseblocks, and keep control flow shallow so reviewers can focus on the important branch. - Exported identifiers must have GoDoc comments that start with the identifier’s name. Use descriptive camelCase names and the
testprefix for_test.gohelpers. - Iterate with
range, initialize slices/maps/channels viamake, and calldeferright after acquiring resources (locks, files, contexts). - Prefer composition over inheritance; embed structs only when it simplifies delegation.
- Drive concurrency through channels and semaphores, drain completion signals, and guard cancellation with
select+default. - Reserve
panic+recoverfor deliberate parse failures and re-panic when the value isn’t the expected type. - Use
selectwithdefaultfor non-blocking cases (e.g., returning buffers to a pool); rely on buffered channels to cap throughput. - Build resource pools via buffered channels that drop excess entries so garbage collection can reclaim unused buffers.
- Prefer request-specific reply channels or channel-of-channel patterns when concurrent callers need individual responses.
- Guard every pointer before dereferencing; if a pointer isn’t needed, accept a value instead (reducing nil checks).
- Wrap external calls with contexts (
context.WithTimeout,WithCancel) and cancel them immediately once the work is done. - Protect storage transactions with locks/
deferunlocks; ensure iterators release resources even if contexts cancel. - Use buffered channel semaphores to throttle goroutines; draining completion channels prevents leaks.
- Document and handle asynchronous errors—don’t ignore the result of sends/receives that can block or fail.
- Run
go test ./...andgo test ./... -racewhen concurrency or shared state is affected. - Re-run heavyweight automation commands whenever your change touches circuits, wasm artifacts, contract deployments, or CLI jobs.
- Integration suites (Docker/Testcontainers) combine API, worker, and persistence flows; rerun them when contracts or artifacts are touched.
- Favor table-driven tests with subtests; keep helpers localized to their test files.
- Track TODOs (especially those touching telemetry, docs, or proto exports) and open follow-up issues when they remain.
- Run
go vet,golangci-lint, andgo mod tidywhen adjusting imports or tooling. - Use short declarations (
:=) for new variables and keep the scope tight to prevent accidental reuse.
- Wrap raw SQL/internal errors before returning them to clients. Messages should identify the failure and map to appropriate HTTP statuses (404 for missing resources, 204 for empties, etc.).
- Use
c.Assert(value, qt.HasLen, N)for length checks instead of comparinglen. - Prefer
qt.DeepEquals,qt.IsNil,qt.Not(qt.IsNil),qt.IsTrue,qt.IsFalse, andqt.Containsover manual comparisons. - Avoid anti-patterns like
c.Assert(len(items), qt.Equals, N)orc.Assert(obj == nil, qt.Equals, false).
- Be factually rigorous; don’t invent or speculate unless you clearly label it as such.
- Question unclear statements; avoid reflexive agreement or hype language.
- Respond directly and concisely; skip filler.
- Admit uncertainty explicitly and ask for clarification when necessary.
- Prioritize accuracy over politeness and don’t oversell capabilities.
- Title format:
[<component>] <brief description>when applicable; otherwise, use a concise but descriptive title. - Document exported API/config changes with GoDoc comments and provide Example functions when they clarify usage.
- List structured logging fields, error wrapping, nil guards, and any control-flow simplifications in the PR body.
- Mention the exact commands needed to reproduce heavy CI steps so reviewers can rerun them verbatim.
- “Use
log.Debugw()always and attach fields.” - “This change touches concurrency—please run
go test -raceand justify the goroutine limits.” - “Document the exported config settings so downstream users know how to enable them.”