Round 6, and one finding exposed something no reviewer mentioned: the majordomo
bump this whole PR depends on was never made. Every test here builds the openai
client directly, so all of them passed against a majordomo release that had
never heard of qwen — a plain "qwen/<model>" in GADFLY_MODELS, the primary way
anyone will use this, would not have resolved at all. A compile error caught it,
which is luck. TestBuiltinCompatProvidersResolveViaRegistry now exercises that
path; the build is what guards the dep itself, since the old release cannot
compile the code below.
On the endpoint-override path, kimi and qwen fell through to openai.New's
OPENAI_API_KEY default whenever GADFLY_API_KEY was unset — sending an OpenAI
key to Moonshot or Alibaba. That is a credential handed to the wrong vendor,
and it is the exact failure majordomo's built-ins are written to prevent; I
reintroduced it one layer up. Both now pass the key unconditionally, so an
absent key is a 401 naming GADFLY_API_KEY rather than a foreign credential on
the wire.
The test job scrubbed the registry credential and left the checkout token in
.git/config, readable by the `go test` it then runs — fixing one credential
while its neighbour sat in the open. persist-credentials: false; nothing in
that job talks to git after checkout.
The cross-language wiring test now QUERIES preflight.sh via a new
gadfly_preflight_providers function instead of regexing its case statement.
Parsing made that file's formatting a contract no linter enforces, where a
harmless reformat breaks a test in another language. Two models flagged it.
Also: grep for the scrub check takes -e, so a password starting with a hyphen
is not read as options; and key_hint stopped repeating key_env in four of five
arms.
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Makes gadfly a consumer of executus (run.Executor compaction/bounding/budget/critic + fanout) and fixes the large-PR token burn in size-gated layers: paginated get_diff, downshift above GADFLY_HUGE_DIFF_BYTES, and a swarm-wide GADFLY_PR_BUDGET_SECS backstop. Small PRs untouched; advisory-only and the static binary preserved. Dogfood swarm reviewed it (6 models, 21 real findings graded + folded in).
Co-authored-by: Steve Dudenhoeffer <[email protected]>
Co-committed-by: Steve Dudenhoeffer <[email protected]>
Bump majordomo to the latest build and accept every llama-swap spelling
(llama-swap/llama-swaps + un-hyphenated llamaswap/llamaswaps) in gadfly's
endpoint switches; the LLM_* llama-swap(s):// DSN path already worked via
majordomo.Parse. README + error messages + endpointProvider alias tests.
Swarm review: 8/9 clean; qwen3-coder's "Blocking" was a false positive
(claimed llamaswap was untested — it has dedicated test cases). Folded in
its one fair nit (README now lists the un-hyphenated aliases).
gofmt clean, go vet quiet, go test -race green.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Co-authored-by: Steve Dudenhoeffer <[email protected]>
Co-committed-by: Steve Dudenhoeffer <[email protected]>
Phase 2: bump majordomo to latest and wire its new llamaswap provider
into gadfly's endpoint switches; add claude-code/sonnet to gadfly's own
dogfood swarm (pin :sha-86f12c1, map CLAUDE_CODE_OAUTH_TOKEN) so the
Phase-1 engine runs as a live competitor; document the Ollama-through-CC
ANTHROPIC_BASE_URL proxy path as example-only.
The 11-model swarm (incl. claude-code/sonnet) reviewed it; 52 findings
graded via the MCP. Folded in the two real ones: a llamaswap
endpointProvider test (caught by claude-code/sonnet, citing CLAUDE.md)
and adding "openai-compatible" to the provider error messages (gpt-oss).
gofmt clean, go vet quiet, go build + go test -race green.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Co-authored-by: Steve Dudenhoeffer <[email protected]>
Co-committed-by: Steve Dudenhoeffer <[email protected]>
Replace the single generic review with a suite of focused specialists, each its
own review+recheck pass, merged into ONE comment (a collapsible section per lens,
led by the worst verdict; the optional `improvements` lens never escalates it).
- cmd/gadfly/specialists.go: built-in lenses + default suite (security, correctness,
maintainability, performance, error-handling) + opt-in (tests, docs, conventions,
improvements). Selection via GADFLY_SPECIALISTS (csv/"all"); custom defs via
GADFLY_SPECIALIST_<NAME> env and a repo .gadfly.yml (specialists + define).
Precedence: built-ins < file < env. Unknown names error but don't sink the run.
- cmd/gadfly/consolidate.go: verdict parse + one-comment render.
- main.go: loop specialists; per-lens failure is an inline notice, never fatal.
Default timeout bumped to 600s (suite runs sequentially).
- base system prompt trimmed to persona+tools+discipline+output; lens-specific
focus is appended per specialist (semantic re-derivation discipline kept in base).
- entrypoint default models -> single model (suite already gives breadth; cost ~=
specialists × models × 2). Adds gopkg.in/yaml.v3.
- docs/examples: README "Specialists" section, examples/.gadfly.yml, stub var,
CLAUDE.md architecture/config. Dynamic `auto` selection is the planned next step.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Replace the hardcoded ollama.Cloud binding with majordomo's provider registry,
so Gadfly can target any backend majordomo supports without code changes.
- cmd/gadfly/model.go: resolveModel() — GADFLY_PROVIDER (default ollama-cloud)
prefixes bare model ids; GADFLY_MODEL may be a full provider/model spec, alias,
or failover chain (verbatim). GADFLY_BASE_URL constructs openai/ollama/anthropic/
google directly at a custom endpoint (OpenAI-compatible + local/remote Ollama).
GADFLY_API_KEY else the provider's standard env var. + buildSpec unit tests.
- run.sh: provider-aware key gate (local Ollama needs none); maps OLLAMA_CLOUD_API_KEY
-> OLLAMA_API_KEY; provider/base-url/key inherited by the binary. Gadfly-branded comment.
- entrypoint.sh: GADFLY_MODELS alias for OLLAMA_REVIEW_MODELS; provider passthrough.
- examples + README: Models & providers section. Upfront: only the Ollama paths
(local + OpenAI-compatible-against-Ollama) are tested; OpenAI/Anthropic/Google
are wired via majordomo but UNTESTED (no spend).
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Standalone, Docker-packaged extraction of the agentic PR reviewer that runs in
Gitea Actions: reads the checked-out repo with read-only tools (read_file/grep/
find_files/get_diff), verifies findings before reporting, two-pass review +
adversarial recheck, posts one labeled comment per model. Advisory only.
- cmd/gadfly: reviewer binary (majordomo + Ollama Cloud), zero deps beyond stdlib + majordomo
- entrypoint.sh: container brains — trigger gating, PR clone, model loop (logic out of YAML)
- Dockerfile: multi-stage; build-time module token never reaches the final image
- .gitea/workflows/build-image.yml: tag v* → build & push image
- examples/: ~15-line consumer stub
- system prompt genericized + hardened to re-derive constants/formulas (semantic bugs)
Vibe-coded with Claude Code; see README disclosure. Advisory, never blocks merge.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>