Files

10 KiB

Agent skills

  • Issues and merge requests use GitLab. For tracker operations, read issue-tracker.md.
  • Use the default triage labels (needs-triage, needs-info, ready-for-agent, ready-for-human, wontfix); see triage-labels.md.
  • Use the single-context domain layout: root CONTEXT.md and docs/adr/. Before exploring a domain, read domain.md and relevant accepted ADRs.

General engineering practices

  • Make the smallest complete change; follow existing structure and conventions, keep responsibilities focused, and avoid unrelated refactoring.
  • Prefer simple, explicit code and composition. Extract logic when duplicated or independently testable; do not add abstractions or dependencies when the existing stack reasonably solves the problem.
  • Add or update tests for changed behavior, and relevant domain documentation for changed behavior, architecture, or business rules.
  • Preserve unrelated user changes. Never commit secrets, credentials, local environment files, debug output, temporary files, or generated artifacts.

Development data lifecycle

  • The application is not in production; development and test data are disposable and should be deleted or reseeded when the model changes.
  • Do not create data migrations, compatibility adapters, dual-read or dual-write paths, or legacy schema support.
  • Replace obsolete schemas, reference data, API contracts, and development documents directly, then update every caller and test in the same change.
  • Do not plan rolling upgrades or backward-compatible deployment until an explicit project decision declares production data must be preserved. Any future production schema management must be explicit, not automatic schema generation.

Frontend: Angular

Architecture and state

  • Organize by feature. Keep pages focused on orchestration, routing, and layout; keep feature-specific components in their feature and reusable presentation in shared components.
  • Split sections that own state, behavior, lifecycle, or reusable UI. Review components approaching 250 lines for extraction; keep substantial business logic outside components and templates and independent of Angular when practical.
  • Use focused, injected services for API access, coordination, and shared state. Follow existing standalone-component and state-management conventions; justify any new state library. Lazy-load feature routes where appropriate.
  • Keep templates readable: move non-trivial calculations to methods, computed values, pipes, or domain utilities. Do not call expensive or state-changing methods from templates.
  • Compute derived state rather than duplicating it. Prefer existing signals, observables, or local state; use async or lifecycle helpers over manual subscriptions and clean up unavoidable subscriptions.
  • Track dynamic lists with trackBy or equivalent syntax and avoid unnecessary change-detection work.
  • Route guards address navigation only; backend authorization remains mandatory.

TypeScript and forms

  • Use strict types and explicit input, output, API, and domain contracts. Use any only for unavoidable integration constraints with a documented reason.
  • Prefer unions/enums over loosely related strings or boolean flags, and immutable transformations where practical. Avoid non-null assertions unless the invariant is guaranteed and clear.
  • Do not use regular-expression .test() calls unless they are the only valid option and the user has explicitly authorized them; prefer readable, maintainable validation alternatives.
  • Validate external API data instead of trusting assertions. Prefer reactive forms for complex or business-critical forms, keep validation consistent with the backend, and show actionable messages.
  • Prevent duplicate pending submissions. Frontend validation is not a security or integrity boundary.

Styling, loading, and accessibility

  • Use Angular Material by default where it covers the UI need. Use Material button directives on native buttons and MatDialog for dialogs; never use unstyled native buttons or browser-native dialogs.
  • Keep all frontend color tokens and Material mappings in frontend/src/_palette.scss. Use its semantic CSS custom properties elsewhere; no raw hex, RGB, HSL, or OKLCH colors outside that file.
  • Keep component styles in .scss, use Sass @use for shared styles, and do not introduce new .css component styles.
  • Reuse frontend/src/_tokens.scss for spacing, radius, breakpoint, and container-query helpers. Prefer Sass nesting, maps, functions, and mixins over repeated responsive or token-fallback declarations.
  • Reuse shared components and styles; scope component styles unless intentionally global. Support the required viewport sizes and avoid layout shifts or blocking interactions.
  • Provide explicit loading, empty, success, and error states. Every user-observable asynchronous operation must expose a truthful loading lifecycle. Prefer content-shaped skeletons for first loads, preserve content with subtle busy feedback for refreshes, and use operation-local progress for actions so unrelated work remains available. Never present pending or failed data as empty or successful.
  • Use semantic HTML before ARIA, native buttons/links for actions, keyboard access, accessible form labels, visible focus, meaningful image alternatives, and correct dialog/overlay focus management. Never communicate status or errors through color alone.

Testing

  • Test observable behavior, not implementation details, for changed components, services, pipes, guards, and utilities.
  • Cover important form validation, loading, and error states. Mock network boundaries, not internal implementation details; use integration/end-to-end coverage for critical journeys where appropriate.

Backend: Java and Spring Boot

Responsibilities and configuration

  • Organize by domain or feature. Keep controllers thin: HTTP, input validation, authentication context, and response mapping. Put application/business logic in services or use cases and persistence in repositories.
  • Use explicit, testable mapping and dedicated API request/response DTOs, not persistence entities or generic maps.
  • Follow the configured Java version. Prefer constructor injection with explicit immutable dependencies; avoid field injection, circular dependencies, and static access to Spring-managed services.
  • Keep domain code framework-independent where practical, with framework annotations at application boundaries.
  • Externalize configuration through typed @ConfigurationProperties, not scattered @Value fields. Keep environment-specific values out of source and use profiles only for genuine environment differences.
  • Use domain-specific types, records for immutable data where supported, and enums for finite states. Keep methods focused and use guard clauses where they improve clarity.
  • Do not use Optional for entity fields, parameters, or collection elements; return empty collections instead of null.
  • Never silently ignore exceptions. Catch broad exceptions only when meaningfully handling, translating, or rethrowing them, and preserve their causes.

API, persistence, and transactions

  • Follow existing REST conventions: resource nouns, standard HTTP methods and appropriate status codes. Validate requests with Jakarta Bean Validation and return consistent structured errors.
  • Document endpoint changes using the existing API documentation approach. Consider pagination for large collections. Make retry-sensitive write operations idempotent when practical.
  • Keep transaction boundaries in services; use @Transactional(readOnly = true) for read operations where appropriate. Keep remote calls, long-running work, and user interaction outside transactions.
  • Fetch only needed data and prevent N+1 queries. Add indexes for identified query patterns, enforce integrity with database constraints as well as validation, and handle concurrent updates where consistency requires it.
  • Apply the development data lifecycle above to schema and API changes.

Security and observability

  • Enforce backend authorization on every protected operation; hidden controls and route guards are insufficient.
  • Validate and sanitize untrusted input. Use parameterized queries or repositories, never query concatenation with untrusted input.
  • Store secrets through configured environment/secret management and apply least privilege to services and database users.
  • Do not expose stack traces, internal class names, database details, or sensitive information in API responses.
  • Use structured logs with appropriate levels and useful non-sensitive identifiers. Do not log passwords, access tokens, session identifiers, personal data, or sensitive payloads.
  • Do not use System.out, print stack traces directly, or duplicate exception logging across layers. Add metrics/tracing for important workflows where already supported.
  • Review new endpoints for authentication, authorization, data exposure, and abuse cases.

Testing

  • Unit-test domain and service behavior. Use integration tests for persistence, security, serialization, transactions, and framework configuration, preferring focused Spring slices when sufficient.
  • Follow the established database test strategy. Keep tests deterministic, isolated, and order-independent.
  • Cover success, validation and authorization failures, important edge cases, and regressions for bug fixes.

Before finishing

  • Review the full task diff for unrelated changes, architectural/naming consistency, oversized units, duplicated logic, unnecessary abstractions, and secret/debug/generated-file leakage.
  • For affected frontend behavior, run the formatter, linter, type checker, and relevant tests. For affected backend behavior, run formatting/style checks, static analysis, and relevant tests. Run the project build when practical.
  • For instruction, configuration, or helper changes, run their relevant validation and behavioral checks; application suites are needed when application behavior is affected.
  • Verify API/database changes are reflected in tests and documentation, and check loading, empty, validation, error, and authorization states where relevant.
  • Report checks run and any command not run or unavailable, with the reason.