3x-ui is a Go (Gin + GORM) web panel that generates configuration, share links and subscriptions for other programs — Xray-core, mihomo, sing-box, mtg-multi — and is deployed by operators who upgrade in place. Judge findings by what breaks for those consumers and operators, not by style.
Reserve blocking severity for:
internal/web/controller/, session and
middleware code, the PUBLIC internal/sub/ subscription server, and Xray
config generation in internal/xray/.runtime.Runtime
(internal/web/runtime/) and calls internal/xray/api.go directly, or
dispatches from a controller or cron job. It passes every local test and
silently breaks every multi-node deployment.internal/database/db.go, one that behaves differently on SQLite and
PostgreSQL, or one that loses or overwrites operator data on upgrade or
rollback. There are no migration files and no down-migrations.internal/util/link/ + internal/sub/, TS
frontend/src/lib/xray/, TS docs/lib/xray/) diverge from one another..github/workflows/: this repository runs workflows with
secrets against a public fork stream. Untrusted expression interpolation
into run: blocks, broadened permissions, weakened guards, or a job that
executes pull-request code is blocking.Style, naming and refactoring suggestions are nits at most.
g.POST/g.GET in internal/web/controller/ needs the whole chain:
an entry in frontend/src/pages/api-docs/endpoints.ts, regenerated
artefacts (make gen), any new API-boundary struct added to StructAllow
in tools/openapigen/main.go, and frontend/public/openapi.json copied to
docs/public/openapi.json with the docs MDX regenerated
(cd docs && pnpm gen:api). CI checks the first three; the docs copy is
checked by nothing — a missed copy is blocking, not a nit.internal/web/translation/
and is referenced from frontend/src or Go in the same PR.err != nil or len(x) > 0, or was made
green by regenerating golden fixtures or Vitest snapshots is a real finding.npm audit, govulncheck.frontend/src/generated/,
frontend/public/openapi.json, docs/public/openapi.json) or lock files.
Those files being STALE after a source change is reportable; their style
is not.CLAUDE.md rejects such tests outright.file:line citation from this repository,
not an inference from a name.Report at most five nits per review and say "plus N similar" in the summary for the rest. Lead the summary with "No blocking issues" when everything found is a nit. After the first review of a PR, report blocking findings only.
The posted comment is the only part of a review anyone sees, so a bare "no issues found" is a receipt, not a review: nothing in it says whether the diff was read or the run died early. Every comment therefore ends with a short coverage list — one line per area actually checked, naming what was examined and what it turned out to be, plus the head SHA and the size of the diff it covers. Say which claims could not be verified and why, including a check this environment blocked. Keep it under ten lines; it is evidence, not a retelling of the pull request.