# golangci-lint v2 config for the AO backend.
# Run: golangci-lint run ./...   (from backend/)
version: "2"

run:
  timeout: 5m

issues:
  # Report every finding, not the default first-50-per-linter / 3-same.
  max-issues-per-linter: 0
  max-same-issues: 0

linters:
  default: none
  enable:
    # --- correctness ---
    - errcheck # unchecked errors
    - govet # suspicious constructs
    - ineffassign # ineffectual assignments
    - staticcheck # the big static analyzer
    - unused # dead code (funcs/vars/types/fields)
    - errorlint # error wrapping / comparison bugs
    - bodyclose # unclosed HTTP response bodies
    - sqlclosecheck # unclosed sql.Rows/Stmt
    - rowserrcheck # missing rows.Err()
    - nilerr # `return nil` after a non-nil err check
    - makezero # append to a non-zero-len make() slice
    - gocheckcompilerdirectives # malformed //go: directives
    - reassign # reassigning package-level vars from other pkgs
    # --- dead code / boilerplate (the "nuke" linters) ---
    - unparam # unused function params / always-same returns
    - unconvert # unnecessary type conversions
    - wastedassign # assignments never read
    - copyloopvar # redundant loop-var copies (Go 1.22+)
    - prealloc # slices that could be preallocated
    - dupl # copy-pasted code blocks
    # --- style / quality ---
    - revive # configurable golint successor
    - gocritic # opinionated diagnostics + style
    - misspell # typos in comments/strings
    - usestdlibvars # use stdlib consts (http.MethodGet, etc.)
    - predeclared # shadowing predeclared identifiers
    - nakedret # naked returns in long funcs
    # --- security ---
    - gosec

  settings:
    errcheck:
      check-type-assertions: true
    govet:
      enable-all: true
      disable:
        - fieldalignment # struct field ordering is not worth the churn
        - shadow # shadowing `err` in nested scopes is idiomatic Go
    revive:
      rules:
        - { name: exported } # doc comments on every exported symbol
        - { name: blank-imports }
        - { name: context-as-argument }
        - { name: context-keys-type }
        - { name: dot-imports }
        - { name: error-return }
        - { name: error-strings }
        - { name: error-naming }
        - { name: indent-error-flow }
        - { name: errorf }
        - { name: empty-block }
        - { name: superfluous-else }
        - { name: unreachable-code }
        - { name: redefines-builtin-id }
        - { name: range }
        - { name: time-naming }
        - { name: var-declaration }
    gocritic:
      enabled-tags: [diagnostic, performance, style]
      disabled-checks:
        - ifElseChain # overlaps revive/superfluous-else
        - commentedOutCode
        - hugeParam # pass-by-pointer micro-opt; hurts clarity, risks nil/aliasing
        - rangeValCopy # same — copying a struct in range is usually fine
        - unnamedResult # named returns are a style choice, not a defect
    dupl:
      threshold: 140
    gosec:
      excludes:
        - G104 # unchecked errors — errcheck owns this
        - G304 # file inclusion via variable — paths are config/run-file/worktree-derived, not user input
        - G703 # path traversal via taint analysis — same as G304: binary-resolution and worktree-derived paths, not user input
        - G704 # SSRF via taint analysis — the daemon client's host is hardcoded loopback; only the request path varies, so it cannot be steered to an external host

  exclusions:
    generated: lax # skip sqlc/codegen ("Code generated ... DO NOT EDIT")
    rules:
      # Tests: relax the noisiest checks (deliberate error-drops, repeated setup,
      # preallocation, and upgrade-response bodies that don't need closing).
      - path: _test\.go
        linters: [errcheck, dupl, gosec, unparam, gocritic, prealloc, bodyclose]
      # status.go deliberately reports probe failures in the result struct
      # (st.State/st.Error) and returns nil — a down daemon is the status being
      # reported, not a failure of the status command itself.
      - path: internal/cli/status\.go
        linters: [nilerr]
      # The reflect/unsafe field-inspection test is intentional.
      - path: wiring_test\.go
        linters: [gosec]
      # Spawning git/agent subprocesses with computed args is the point.
      - linters: [gosec]
        text: "G204"

formatters:
  enable:
    - goimports
  settings:
    goimports:
      local-prefixes:
        - github.com/aoagents/agent-orchestrator
