Files
sub2api/AGENTS.md
2026-02-28 15:01:20 +08:00

8.3 KiB

Repository Guidelines

Project Structure & Module Organization

  • backend/: Go service. cmd/server is the entrypoint, internal/ contains handlers/services/repositories/server wiring, ent/ holds Ent schemas and generated ORM code, migrations/ stores DB migrations, and internal/web/dist/ is the embedded frontend build output.
  • frontend/: Vue 3 + TypeScript app. Main folders are src/api, src/components, src/views, src/stores, src/composables, src/utils, and test files in src/**/__tests__.
  • deploy/: Docker and deployment assets (docker-compose*.yml, .env.example, config.example.yaml).
  • openspec/: Spec-driven change docs (changes/<id>/{proposal,design,tasks}.md).
  • tools/: Utility scripts (security/perf checks).

Build, Test, and Development Commands

make build                           # Build backend + frontend
make test                            # Backend tests + frontend lint/typecheck
cd backend && make build             # Build backend binary
cd backend && make test-unit         # Go unit tests
cd backend && make test-integration  # Go integration tests
cd backend && make test              # go test ./... + golangci-lint
cd frontend && pnpm install --frozen-lockfile
cd frontend && pnpm dev              # Vite dev server
cd frontend && pnpm build            # Type-check + production build
cd frontend && pnpm test:run         # Vitest run
cd frontend && pnpm test:coverage    # Vitest + coverage report
python3 tools/secret_scan.py         # Secret scan

Coding Style & Naming Conventions

  • Go: format with gofmt; lint with golangci-lint (backend/.golangci.yml).
  • Respect layering: internal/service and internal/handler must not import internal/repository, gorm, or redis directly (enforced by depguard).
  • Frontend: Vue SFC + TypeScript, 2-space indentation, ESLint rules from frontend/.eslintrc.cjs.
  • Naming: components use PascalCase.vue, composables use useXxx.ts, Go tests use *_test.go, frontend tests use *.spec.ts.

Go & Frontend Development Standards

  • Control branch complexity: if nesting must not exceed 3 levels. Refactor with guard clauses, early returns, helper functions, or strategy maps when deeper logic appears.
  • JSON hot-path rule: for read-only/partial-field extraction, prefer gjson over full encoding/json struct unmarshal to reduce allocations and improve latency.
  • Exception rule: if full schema validation or typed writes are required, encoding/json is allowed, but PR must explain why gjson is not suitable.

Go Performance Rules

  • Optimization workflow rule: benchmark/profile first, then optimize. Use go test -bench, go tool pprof, and runtime diagnostics before changing hot-path code.
  • For hot functions, run escape analysis (go build -gcflags=all='-m -m') and prioritize stack allocation where reasonable.
  • Every external I/O path must use context.Context with explicit timeout/cancel.
  • When creating derived contexts (WithTimeout / WithDeadline), always defer cancel() to release resources.
  • Preallocate slices/maps when size can be estimated (make([]T, 0, n), make(map[K]V, n)).
  • Avoid unnecessary allocations in loops; reuse buffers and prefer strings.Builder/bytes.Buffer.
  • Prohibit N+1 query patterns; batch DB/Redis operations and verify indexes for new query paths.
  • For hot-path changes, include benchmark or latency comparison evidence (e.g., go test -bench before/after).
  • Keep goroutine growth bounded (worker pool/semaphore), and avoid unbounded fan-out.
  • Lock minimization rule: if a lock can be avoided, do not use a lock. Prefer ownership transfer (channel), sharding, immutable snapshots, copy-on-write, or atomic operations to reduce contention.
  • When locks are unavoidable, keep critical sections minimal, avoid nested locks, and document why lock-free alternatives are not feasible.
  • Follow sync guidance: prefer channels for higher-level synchronization; use low-level mutex primitives only where necessary.
  • Avoid reflection and interface{}-heavy conversions in hot paths; use typed structs/functions.
  • Use sync.Pool only when benchmark proves allocation reduction; remove if no measurable gain.
  • Avoid repeated time.Now()/fmt.Sprintf in tight loops; hoist or cache when possible.
  • For stable high-traffic binaries, maintain representative default.pgo profiles and keep go build -pgo=auto enabled.

Data Access & Cache Rules

  • Every new/changed SQL query must be checked with EXPLAIN (or EXPLAIN ANALYZE in staging) and include index rationale in PR.
  • Default to keyset pagination for large tables; avoid deep OFFSET scans on hot endpoints.
  • Query only required columns; prohibit broad SELECT * in latency-sensitive paths.
  • Keep transactions short; never perform external RPC/network calls inside DB transactions.
  • Connection pool must be explicitly tuned and observed via DB.Stats (SetMaxOpenConns, SetMaxIdleConns, SetConnMaxIdleTime, SetConnMaxLifetime).
  • Avoid overly small MaxOpenConns that can turn DB access into lock/semaphore bottlenecks.
  • Cache keys must be versioned (e.g., user_usage:v2:{id}) and TTL should include jitter to avoid thundering herd.
  • Use request coalescing (singleflight or equivalent) for high-concurrency cache miss paths.

Frontend Performance Rules

  • Route-level and heavy-module code splitting is required; lazy-load non-critical views/components.
  • API requests must support cancellation and deduplication; use debounce/throttle for search-like inputs.
  • Minimize unnecessary reactivity: avoid deep watch chains when computed/cache can solve it.
  • Prefer stable props and selective rendering controls (v-once, v-memo) for expensive subtrees when data is static or keyed.
  • Large data rendering must use pagination or virtualization (especially tables/lists >200 rows).
  • Move expensive CPU work off the main thread (Web Worker) or chunk tasks to avoid UI blocking.
  • Keep bundle growth controlled; avoid adding heavy dependencies without clear ROI and alternatives review.
  • Avoid expensive inline computations in templates; move to cached computed selectors.
  • Keep state normalized; avoid duplicated derived state across multiple stores/components.
  • Load charts/editors/export libraries on demand only (dynamic import) instead of app-entry import.
  • Core Web Vitals targets (p75): LCP <= 2.5s, INP <= 200ms, CLS <= 0.1.
  • Main-thread task budget: keep individual tasks below ~50ms; split long tasks and yield between chunks.
  • Enforce frontend budgets in CI (Lighthouse CI with budget.json) for critical routes.

Performance Budget & PR Evidence

  • Performance budget is mandatory for hot-path PRs: backend p95/p99 latency and CPU/memory must not regress by more than 5% versus baseline.
  • Frontend budget: new route-level JS should not increase by more than 30KB gzip without explicit approval.
  • For any gateway/protocol hot path, attach a reproducible benchmark command and results (input size, concurrency, before/after table).
  • Profiling evidence is required for major optimizations (pprof, flamegraph, browser performance trace, or bundle analyzer output).

Quality Gate

  • Any changed code must include new or updated unit tests.
  • Coverage must stay above 85% (global frontend threshold and no regressions for touched backend modules).
  • If any rule is intentionally violated, document reason, risk, and mitigation in the PR description.

Testing Guidelines

  • Backend suites: go test -tags=unit ./..., go test -tags=integration ./..., and e2e where relevant.
  • Frontend uses Vitest (jsdom); keep tests near modules (__tests__) or as *.spec.ts.
  • Enforce unit-test and coverage rules defined in Quality Gate.
  • Before opening a PR, run make test plus targeted tests for touched areas.

Commit & Pull Request Guidelines

  • Follow Conventional Commits: feat(scope): ..., fix(scope): ..., chore(scope): ..., docs(scope): ....
  • PRs should include a clear summary, linked issue/spec, commands run for verification, and screenshots/GIFs for UI changes.
  • For behavior/API changes, add or update openspec/changes/... artifacts.
  • If dependencies change, commit frontend/pnpm-lock.yaml in the same PR.

Security & Configuration Tips

  • Use deploy/.env.example and deploy/config.example.yaml as templates; do not commit real credentials.
  • Set stable JWT_SECRET, TOTP_ENCRYPTION_KEY, and strong database passwords outside local dev.