This is the repository-wide source of truth for AI coding agents. A nested AGENTS.md adds rules for its subtree and must not repeat this file.
- Apply only the sections relevant to the task. A documentation edit does not require backend builds, deployment checks, or architecture exploration.
- Start with the requested outcome and the affected files. Expand discovery when a dependency, caller, or concrete uncertainty requires it; do not audit the whole repository by default.
- Use current source, executable configuration, and observed results to establish facts. Memory, documentation, and graph results are navigation aids; check their project and freshness before relying on them. Do not invent missing APIs, commands, files, or test results.
- Choose the simplest change that satisfies the request and preserves existing contracts. Use a plan, skill, or delegated review when it adds value to the task, rather than as a mandatory ceremony for every edit.
- Resolve routine, reversible choices using existing patterns. Ask when missing information materially affects correctness, scope, authorization, or an irreversible action; do not ask again for authorization already given for that action.
- A request to implement or fix an issue authorizes the necessary in-scope investigation, local edits, regression checks, and relevant documentation updates. Continue through these steps without a separate implementation confirmation. Review-only, planning-only, and explicit pre-edit approval requests remain binding; external and destructive actions retain their existing approval requirements.
- Stop exploring when the affected behavior is understood and the relevant checks answer the remaining risks. Revisit only when new evidence, failures, or changes justify it. If blocked, report the specific limit and continue independent work; do not repeat an unchanged failing approach.
- Report what changed, what was actually verified, and any remaining limitations. Distinguish inference, static inspection, runtime verification, and remote delivery; a failed or skipped check is not a pass.
UltiCode is an online-judge platform with these main surfaces:
| Path | Responsibility |
|---|---|
services/auth/ |
Auth owner service: credentials, OAuth, sessions, JWT, RBAC |
services/admin/ |
Admin owner service: governance, audit, settings, monitoring, backup |
services/app/ |
App owner service: OJ and general user business (parent of app-web/ boot shell + modules/ private domains) |
services/judge/ |
Independent Judge worker service: separate from app-web, reuses the storage-free backend-judge-runtime plus owner APIs; Redis Streams consumer + Docker sandbox, Dubbo remote adapters, no HTTP and no business tables |
services/ |
Java / Spring Boot Maven parent/reactor; platform/ (common, web-security), api/ (Dubbo contracts), five owner services, two independent workers, and the shared judge runtime |
apps/console/ |
Vue 3 user application |
apps/management/ |
Vue 3 administrator application |
packages/ |
Focused frontend packages shared by both applications |
init-db/migrations/ |
Canonical Flyway migrations |
docker/ |
Runtime infrastructure and judge sandbox |
scripts/dev/ |
Supported local startup, migration, and verification entry points |
docs/ |
六个核心主题文档;项目问题与运行细节由 services/docs/、源码、配置和门禁维护;从 docs/index.md 开始 |
Read the nearest guide before editing services/, apps/console/, apps/management/, or packages/.
- Preserve the backend flow
controller -> service -> mapper -> entityand existing domain-module boundaries. Do not introduce a parallel architecture for a local change. - Reuse focused packages under
packages/for shared frontend behavior. Extract duplicated behavior when needed by the task; do not force app-specific behavior into a shared abstraction. - Keep request/response contracts aligned across backend, shared types, and both frontends. Preserve the existing
Resultenvelope and established field-name mappings.
- Inspect the implementation, configuration, tests, and local guide before changing behavior. Treat code and executable configuration as authoritative when documentation disagrees.
- Keep changes scoped. Preserve unrelated work in a dirty worktree and do not rewrite generated or historical files without a task-specific reason.
- Formatting follows the affected module's formatter/linter configuration; where none exists, match nearby code. Do not impose extra line-length, naming, comment, import-order, or syntax preferences through agent rules.
- Format changed files or ranges only. Do not run whole-tree auto-fixes or add formatting tools unless the task calls for them; inspect any tool-generated diff.
- Validate inputs at system boundaries, use typed DTOs and parameterized database access, and follow existing error-handling patterns.
- Add or update tests for changed behavior and important failure paths. Security-sensitive rendering and URL handling require malicious-input regressions.
- Only
packages/thememay write thedata-themeattribute;useThemeForceUpdateis test-only. - Use relevant project skills when explicitly requested or when their workflow helps the task. Missing optional tools or skills are not blockers if direct inspection and supported checks provide the needed evidence.
- Before completion, review the diff against the request and applicable security, compatibility, and failure-path concerns. Use a formal review workflow for substantial or high-risk changes, or when requested; a focused self-review is sufficient for small, low-risk edits.
- Never commit, print, or hardcode credentials. Runtime secrets belong in
.env, CI secrets, or the deployment secret store; JWT secrets must be at least 32 characters. - Access and refresh tokens remain in HttpOnly cookies. Refresh tokens use the database-backed hash-only issue/rotate/revoke flow; never store plaintext refresh tokens or accept an access token as a refresh credential.
- OAuth state remains bound to an HttpOnly cookie and is consumed atomically from Redis.
- WebSocket authentication accepts only the
access_tokencookie, never query, URL, or client-controlled STOMP tokens. /admin/**and privileged methods requireADMINorSUPER_ADMIN. Audit identity comes from the authenticated principal, not request data.- Markdown and KaTeX HTML must pass through
packages/markdown-utils; do not bypass DOMPurify or send unsanitized output tov-html. - Base and production Compose configurations must not publish MySQL, Redis, Nacos, or backend ports. Development exposure belongs only in
docker/docker-compose.dev.ymland must bind to loopback. Keep Nacos authentication enabled and its default account disabled. - Do not add usable default users or passwords to migrations. Initial administrator provisioning remains opt-in.
init-db/migrations/is the only migration source. UseV{timestamp}__Description.sql.- Never edit an applied migration; add a later, backward-compatible migration.
- Do not bypass
V20260606130000__Secure_Refresh_Tokens_And_Lock_Seed_Accounts.sqlor reintroduce usable seed credentials. - Use the
ulticode-db-migrationskill when available.
Select checks proportional to the changed surface and risk; the commands below are alternatives, not a mandatory sequence. Documentation-only edits normally need a diff, link/path checks where relevant, and whitespace validation. For behavior changes, run focused regression checks first; broaden for cross-module effects or unresolved risks. Do not repeat equivalent successful checks without a reason.
Prefer the supported wrapper when broad verification is needed:
./scripts/dev/test.sh quick
./scripts/dev/test.sh full
./scripts/dev/test.sh integrationTargeted checks:
# services/ Maven reactor; run from repository root
(cd services && ./mvnw compile -B)
(cd services && ./mvnw test -B)
(cd services && ./mvnw -Dtest='*IT' test -B) # Surefire excludes *IT by default
(cd services && ./mvnw verify -B) # includes JaCoCo report and thresholds
# apps/console/
(cd apps/console && pnpm lint)
(cd apps/console && pnpm type-check)
(cd apps/console && pnpm test)
(cd apps/console && pnpm build)
# apps/management/
(cd apps/management && pnpm lint)
(cd apps/management && pnpm type-check)
(cd apps/management && pnpm test)
(cd apps/management && pnpm build)
# apps/management/ when translations change
(cd apps/management && pnpm validate:i18n-keys)
# a changed shared package, when the scripts exist in its package.json
pnpm --dir packages/<package> type-check
pnpm --dir packages/<package> testFor Compose changes, validate affected development and production combinations. For migrations, run the applicable migration checks; Compose validation is additionally needed when deployment configuration changes. Commands for both Compose combinations:
docker compose --project-directory . --env-file .env -f docker/docker-compose.yml -f docker/docker-compose.dev.yml config >/dev/null
docker compose --project-directory . --env-file .env -f docker/docker-compose.yml -f docker/docker-compose.prod.yml config >/dev/null
git diff --checkDo not use /actuator/health as a readiness check; Actuator is not exposed. Use the existing public API, frontend roots, PM2 state, and container health checks.
- Apply this section only when the task explicitly requests remote testing, deployment, or tunnel access. Resolve the remote host, checkout, branch, and ports from the current environment; otherwise follow the repository's normal local entry points.
- Before remote execution, read the relevant sections of
docs/DEVELOPMENT.md,docs/OPERATIONS.md, and the applicable Services runbook; use their supportedscripts/dev/*and manifest entry points. - For data backfill or cutover runbooks, perform the source/target, checksum, outbox, and writer checks required by that runbook; only for Submission cutover update its marker after verification passes. Pure schema migrations follow their migration gate and do not require a cutover marker.
- For personal local access to a remote test stack, prefer SSH local port forwarding. Use a Cloudflare Quick Tunnel only when public or cross-device access is explicitly required; scope it to frontend entries, protect administrative surfaces, and remove it after testing.
- Treat explicit exit codes, readiness responses, parsed PM2 state, and Compose health as separate evidence. Process
onlineor containerhealthyalone is not a complete deployment proof. - Keep dynamic URLs, container names, test counts, commit IDs, temporary failures, and runtime logs out of this file; record current evidence only in the task report or the canonical document that owns it.
- Review
git diffandgit diff --checkbefore completion. Use conventional commit subjects:<type>: <description>. - Do not discard user changes or use destructive Git commands unless explicitly requested.
- Pushing, merging, publishing, changing third-party resources, rotating remote credentials, and rewriting history require explicit user authorization for the action. An explicit request to perform that action is authorization within its stated scope; do not require a second confirmation unless the scope or risk changes.
- Keep repository-wide agent rules only in this file. Nested guides contain only durable, subtree-specific constraints.
- Do not record volatile counts, file lengths, temporary review findings, planned architecture, or facts directly inferable from package/build configuration.
- Update the affected canonical document under
docs/in the same change when behavior, commands, paths, contracts, or architecture boundaries change. Keep implementation and executable configuration authoritative. - Read documentation through
docs/index.md: it maps the six current core documents. For a task, read the relevant core entry first, then the owning code/config/tests; useservices/docs/only for its owner-maintained issue and runbook material. - Do not add a new task/session/date-specific document or duplicate a core topic. Keep current documentation in the six core files; task execution state stays in ignored local agent directories, and open service issues remain in
services/docs/SERVICES_ISSUES.md.
A task is complete when the requested outcome and authorized delivery steps are fulfilled, applicable verification passes, the diff contains no unintended changes, security and compatibility constraints are preserved, and affected documentation is current. Reporting a failed or unavailable check does not itself satisfy completion. Resolve failures caused by the change within scope; otherwise report the remaining work and specific blocker, continue independent authorized work, and distinguish implementation complete from verification or delivery blocked.
- Use
docs/index.mdfor broad documentation navigation. For code discovery, use an available, relevant graph to narrow the search, then inspect the source needed for the claim or edit. Avoid duplicating the same lookup across graph tools. - When graphify is useful and
graphify-out/graph.jsonexists, usegraphify query "<question>",graphify path "<A>" "<B>", orgraphify explain "<concept>". The full report is for broad architecture questions, not routine edits. - If a tool is unavailable or its index is stale, incomplete, or for another project, use targeted source reads and searches. An empty graph result does not prove absence; scope negative claims to what was checked.
- Refresh a graph when the task needs updated relationships or the user requests it. Documentation-only edits do not require graph updates; preserve unrelated generated changes.
- When the user explicitly invokes
/graphify, follow the installed graphify skill.
This project has a knowledge graph at graphify-out/ with god nodes, community structure, and cross-file relationships.
When the user types /graphify, use the installed graphify skill or instructions before doing anything else.
Rules:
- For codebase questions, first run
graphify query "<question>"when graphify-out/graph.json exists. Usegraphify path "<A>" "<B>"for relationships andgraphify explain "<concept>"for focused concepts. These return a scoped subgraph, usually much smaller than GRAPH_REPORT.md or raw grep output. - Dirty graphify-out/ files are expected after hooks or incremental updates; dirty graph files are not a reason to skip graphify. Only skip graphify if the task is about stale or incorrect graph output, or the user explicitly says not to use it.
- If graphify-out/wiki/index.md exists, use it for broad navigation instead of raw source browsing.
- Read graphify-out/GRAPH_REPORT.md only for broad architecture review or when query/path/explain do not surface enough context.
- After modifying code, run
graphify update .to keep the graph current (AST-only, no API cost).