mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-09-03 17:07:15 +00:00
ac193cd9d3
The issue analyst moves verbatim from claude-bot.yml into its own claude-issue-analyst.yml, so claude-bot.yml now holds only the pull-request side: review, @claude mentions and conflict resolution. The review job's briefing was a single 2,600-character quoted string inside claude_args, unreadable and unreviewable. It now lives in .github/claude/review-job.md, assembled at run time with a "This run" section that hands the reviewer the pinned head SHA, the pull request and the exact check-runs command, and reaches the CLI through --append-system-prompt-file. The agent-mode action sets no system-prompt append of its own, so the file flag cannot collide with one. Findings no longer carry the fix: REVIEW.md and the brief both forbid suggestion blocks, patches and replacement snippets, overriding the code-review skill's --comment step, which attaches a committable suggestion to any small fix. A finding states what is wrong, where, what triggers it and what breaks; the maintainer decides the change.
157 lines
8.4 KiB
Markdown
157 lines
8.4 KiB
Markdown
# Review instructions
|
|
|
|
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.
|
|
|
|
## Severity
|
|
|
|
Mark every finding with exactly one of these, at the start of the finding:
|
|
|
|
| Marker | Severity | Use it for |
|
|
| --- | --- | --- |
|
|
| 🔴 | Important | A defect this pull request introduces or makes worse, in one of the classes under "What Important means here". Worth fixing before it merges. |
|
|
| 🟡 | Nit | Style, naming, refactoring, and an ordinary `CLAUDE.md` violation the change introduces — a source comment block over two lines, a fix larger than the bug it removes, a test `CLAUDE.md` rejects outright. |
|
|
| 🟣 | Pre-existing | A real bug you hit while reading that this pull request neither introduced nor made worse. |
|
|
|
|
Not every `CLAUDE.md` rule is a nit. The three listed below — the dispatch
|
|
rule, the migration rule, the endpoint chain — are Important, because each one
|
|
passes every local test and breaks a real deployment.
|
|
|
|
Severity follows what this pull request did, not how alarming the defect looks
|
|
on its own. One the change worsens is 🔴 for the regression it added, not for
|
|
the whole defect; one it merely brought into view is 🟣.
|
|
|
|
Checking what this panel emits means reading far more code than the diff
|
|
changes, so pre-existing bugs surface on every review. One already on the base
|
|
branch stays 🟣 however bad it is: this pull request did not cause it, so it
|
|
cannot be a reason to hold this pull request. Say in one clause that it
|
|
predates the change. The exception is a live security hole on an exposed
|
|
surface — still 🟣, but open the summary with it.
|
|
|
|
## What Important means here
|
|
|
|
- Security on the exposed surfaces: `internal/web/controller/`, session and
|
|
middleware code, the PUBLIC `internal/sub/` subscription server, and Xray
|
|
config generation in `internal/xray/`.
|
|
- A state-changing inbound or client operation that bypasses `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.
|
|
- A schema or model change without a matching hand-written migration in
|
|
`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.
|
|
- A change to what the panel emits on the wire — Xray config JSON, share
|
|
links, subscription/Clash YAML, mtg-multi TOML — that a downstream client
|
|
would reject or read differently, or that makes the three independent link
|
|
implementations (Go `internal/util/link/` + `internal/sub/`, TS
|
|
`frontend/src/lib/xray/`, TS `docs/lib/xray/`) diverge from one another.
|
|
- Any edit to `.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.
|
|
|
|
## Always check
|
|
|
|
- A new `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 Important, not a nit.
|
|
- A bug fix carries a test that would fail without the fix. A test that cannot
|
|
tell the broken behaviour from the fixed one passes before and after, so it
|
|
certifies nothing and is itself the finding — asserting only `err != nil` or
|
|
`len(x) > 0`, or going green by regenerating golden fixtures or Vitest
|
|
snapshots.
|
|
- No second way to do a thing already decided: Go tests are stdlib `testing`
|
|
(never testify), the panel is Ant Design (never Tailwind or shadcn). Neither
|
|
golangci-lint nor oxlint forbids the import, so it passes CI clean.
|
|
|
|
## Do not report
|
|
|
|
- Anything CI already enforces: golangci-lint and gofumpt, oxlint, format
|
|
and typecheck, govulncheck, and `npm audit --omit=dev --audit-level=high`.
|
|
A dev-dependency advisory is out of scope on purpose: it ships to nobody.
|
|
- The contents of generated files (`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.
|
|
- Missing tests for getters, constants, renames or pure map lookups —
|
|
`CLAUDE.md` rejects such tests outright.
|
|
- A missing or unreferenced i18n key.
|
|
`frontend/src/test/i18n-dead-keys.test.ts` pins the 13 locale files in
|
|
`internal/web/translation/` in both directions, so the `frontend` job is
|
|
already red. Report the failing check, not the key.
|
|
|
|
## A higher bar, not silence
|
|
|
|
Everything named under "What Important means here" gets full scrutiny. Two
|
|
areas do not — they earn review, but report there only what you are
|
|
near-certain about and that actually breaks something:
|
|
|
|
- `docs/` — the standalone Fumadocs site, with its own CI and its own
|
|
dependency tree. `docs/lib/xray/` is the exception and gets full scrutiny:
|
|
it is the third link implementation.
|
|
- `internal/web/translation/` — the key set is CI's job and the wording of a
|
|
translation is nobody's here.
|
|
|
|
## Verification bar
|
|
|
|
- A claim about behaviour needs a `file:line` citation from this repository,
|
|
not an inference from a name.
|
|
- A claim that a downstream client rejects or requires a wire-format detail —
|
|
a config key, JSON tag, URI query parameter, YAML or TOML key, an encoding
|
|
or hash choice — must name the upstream symbol that decides it (repository,
|
|
file, identifier). If you cannot verify it, keep the finding but say
|
|
explicitly that it is unverified instead of asserting it.
|
|
- "CI passed" is a claim too, and needs the same evidence: say it only of a
|
|
run you actually read. A green one proves less here than it looks — only
|
|
`postgres-durable-first` runs against PostgreSQL, `go-test` and `race` are
|
|
SQLite, and `XRAY_E2E_BINARY` and `XUI_SCALE_TEST` are set by no job, so
|
|
those tests have never run in CI at all. Where a change touches dialect,
|
|
migration or Xray gRPC code that no job exercised, say it is unverified
|
|
rather than repeating a green tick as proof.
|
|
|
|
## Cap the volume
|
|
|
|
🔴 findings are never capped. Report every one.
|
|
|
|
Report at most five 🟡 nits and at most three 🟣 pre-existing bugs. Past that,
|
|
say "plus N similar" in the summary instead of posting them.
|
|
|
|
A cap decides WHICH ones survive, so choose rather than truncate: the same nit
|
|
repeated across files is ONE finding with a count, not five slots; a nit in
|
|
code this pull request wrote outranks one in code it only moved; and a nit
|
|
nobody would act on does not deserve a slot at all.
|
|
|
|
After the first review of a pull request, report 🔴 findings only: a one-line
|
|
fix must not reach round seven on style.
|
|
|
|
## What the comment must show
|
|
|
|
Open with a one-line tally — `2 🔴 / 4 🟡 / 1 🟣` — so the author sees the
|
|
shape of the review before the detail. When nothing is 🔴, lead with
|
|
`No blocking issues` and put the tally after it.
|
|
|
|
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 that coverage list under ten lines; it is
|
|
evidence, not a retelling of the pull request.
|
|
|
|
## A finding is a report, not a patch
|
|
|
|
A finding says what is wrong, where (`file:line`), what triggers it and what
|
|
breaks. It never carries the fix: no `suggestion` block, no patch, no
|
|
replacement snippet, no rewritten function, no "suggested fix" section — in
|
|
the summary and in an inline comment alike. One clause naming where the fix
|
|
belongs is the most it may add. The maintainer decides the change; a review
|
|
that writes it out puts unreviewed code one click from the branch.
|