12 KiB
12 KiB
Agent skills
Issue tracker
Issues and merge requests (MRs) are tracked in this repository's GitLab instance. See issue-tracker.md.
Triage labels
Use the default triage labels (needs-triage, needs-info, ready-for-agent, ready-for-human, wontfix). See triage-labels.md.
Domain docs
Use the single-context documentation layout. See domain.md.
General engineering practices
- Make the smallest change that fully solves the issue.
- Follow the existing project structure and conventions before introducing new patterns.
- Prefer simple, explicit code over unnecessary abstraction.
- Keep classes, components, and functions focused on one responsibility.
- Extract reusable logic when it is duplicated or independently testable.
- Avoid unrelated refactoring in feature or bug-fix merge requests.
- Do not introduce a new dependency when the existing stack can reasonably solve the problem.
- The application is not in production. Change development contracts and schemas directly when the domain model changes; update all callers and tests together instead of preserving backward compatibility.
- Add or update tests for changed behavior.
- Do not commit secrets, tokens, credentials, generated artifacts, or local environment files.
- Update relevant domain documentation when behavior, architecture, or business rules change.
Frontend: Angular
Components
- Keep components small and focused on a single responsibility.
- Split a component when a section has its own state, behavior, lifecycle, or reusable UI.
- Keep page-level components focused on orchestration, routing, and layout.
- Move reusable presentation elements into shared components.
- Keep feature-specific components inside their feature directory.
- Prefer composition over components with many configuration flags.
- Avoid large component files. Components approaching 250 lines should be reviewed for extraction opportunities.
- Do not place substantial business logic directly in templates or components.
Angular architecture
- Organize code by feature rather than only by technical type.
- Keep domain and business logic independent from Angular when practical.
- Use services for API access, application coordination, and shared state.
- Use dependency injection instead of manually constructing services.
- Keep services focused; avoid catch-all services with unrelated responsibilities.
- Prefer standalone components where they match the existing project architecture.
- Lazy-load feature routes where appropriate.
- Use route guards only for navigation concerns, not as the sole enforcement of security rules.
- Follow the repository's established state-management approach. Do not introduce another state-management library without justification.
Templates and state
- Keep templates readable and free of complex expressions.
- Move non-trivial calculations into component methods, computed values, pipes, or domain utilities.
- Do not call expensive or state-changing methods from templates.
- Prefer Angular signals, observables, or local component state according to the existing codebase conventions.
- Do not duplicate derived state. Compute values from their source whenever practical.
- Avoid manual subscriptions when the
asyncpipe, signals, or framework lifecycle helpers can manage them. - Ensure subscriptions are cleaned up when manual subscription is unavoidable.
- Use
trackByor Angular's equivalent tracking syntax for dynamic lists. - Avoid unnecessary change-detection work.
TypeScript
- Use strict TypeScript types.
- Do not use
anyunless integration constraints make it unavoidable and the reason is documented. - Define explicit input, output, API, and domain types.
- Prefer unions and enums over loosely related strings or multiple boolean flags.
- Use immutable transformations where practical.
- Do not use regular-expression
.test()calls unless they are the only valid option and the user has explicitly authorized them; prefer more readable, maintainable validation alternatives. - Avoid non-null assertions unless the invariant is guaranteed and clear.
- Validate data received from external APIs instead of trusting type assertions.
Forms
- Prefer reactive forms for complex or business-critical forms.
- Keep validation rules consistent between the frontend and backend.
- Display actionable validation messages.
- Prevent duplicate submissions while a request is pending.
- Do not rely on frontend validation for security or data integrity.
Styling and user experience
- Reuse the existing design system, shared components, spacing rules, and design tokens.
- Avoid duplicating styles already provided by shared components.
- Keep component styles scoped unless a style is intentionally global.
- Ensure layouts work across supported viewport sizes.
- Provide explicit loading, empty, success, and error states.
- Every user-observable asynchronous frontend operation must expose a truthful loading lifecycle. Prefer content-shaped skeletons for first loads, preserve established content with subtle busy feedback during refreshes, and use operation-local progress for actions so unrelated work remains available; never present pending or failed data as an empty or successful result.
- Avoid unexpected layout shifts and blocking interactions.
Accessibility
- Use semantic HTML before adding ARIA attributes.
- Use native buttons and links for interactive actions.
- Ensure all interactive elements are keyboard accessible.
- Associate form controls with visible or accessible labels.
- Preserve visible focus indicators.
- Provide alternative text for meaningful images.
- Ensure dialogs and overlays manage focus correctly.
- Do not communicate status or errors through color alone.
Angular testing
- Test observable behavior rather than implementation details.
- Add unit tests for components, services, pipes, guards, and utilities when their behavior changes.
- Cover important form validation and error states.
- Mock network boundaries rather than internal implementation details.
- Add integration or end-to-end coverage for critical user journeys when appropriate.
Backend: Java and Spring Boot
Structure and responsibilities
- Keep controllers thin.
- Controllers should handle HTTP concerns, input validation, authentication context, and response mapping.
- Put application and business logic in dedicated services or use-case classes.
- Keep persistence logic in repositories.
- Do not expose persistence entities directly through public APIs.
- Use dedicated request and response DTOs at API boundaries.
- Keep mapping logic explicit and testable.
- Organize code by domain or feature where possible.
- Avoid utility classes that accumulate unrelated behavior.
Java practices
- Follow the Java version and conventions already configured in the repository.
- Prefer constructor injection over field injection.
- Make dependencies explicit and immutable where possible.
- Use descriptive names and small methods.
- Avoid deeply nested conditionals; use guard clauses where they improve clarity.
- Prefer domain-specific types over primitive strings and numbers for important concepts.
- Use records for immutable data carriers when supported by the project.
- Use enums for finite domain states.
- Do not use
Optionalfor entity fields, method parameters, or collection elements. - Return empty collections instead of
null. - Do not catch broad exceptions unless they are rethrown, translated, or handled meaningfully.
- Do not silently ignore exceptions.
Spring Boot practices
- Use constructor-based dependency injection.
- Keep configuration externalized through Spring configuration properties.
- Use typed
@ConfigurationPropertiesinstead of scattering@Valueannotations. - Keep environment-specific values outside source code.
- Use profiles only for genuine environment differences.
- Avoid circular dependencies.
- Do not use static access to Spring-managed services.
- Use framework annotations at the application boundary and keep domain code framework-independent where practical.
API design
- Follow the repository's existing REST conventions.
- Use nouns for resource paths and standard HTTP methods.
- Return appropriate HTTP status codes.
- Keep request and response contracts coherent with the current model; replace obsolete development contracts rather than adding compatibility layers.
- Use explicit DTOs instead of generic maps.
- Validate incoming requests with Jakarta Bean Validation.
- Return consistent, structured error responses.
- Do not expose stack traces, internal class names, database details, or sensitive information.
- Document new or changed endpoints using the project's API documentation approach.
- Consider pagination for endpoints returning potentially large collections.
- Make retry-sensitive write operations idempotent when practical.
Persistence and transactions
- Keep transaction boundaries in the service layer.
- Use
@Transactional(readOnly = true)for read-only service operations when appropriate. - Avoid long-running work, remote calls, or user interaction inside database transactions.
- Prevent N+1 query problems.
- Fetch only the data required for the use case.
- Use explicit database migrations for schema changes.
- Never rely on automatic schema generation in production.
- Add indexes only when supported by an identified query pattern.
- Preserve data integrity with database constraints in addition to application validation.
- Handle concurrent updates explicitly where data consistency requires it.
Security
- Enforce authorization on the backend for every protected operation.
- Never rely on hidden frontend controls or route guards for authorization.
- Validate and sanitize untrusted input.
- Use parameterized queries or repository abstractions; never concatenate untrusted input into queries.
- Do not log passwords, access tokens, session identifiers, personal data, or sensitive request payloads.
- Store secrets in the configured secret-management or environment mechanism.
- Use least-privilege access for services and database users.
- Review new endpoints for authentication, authorization, data exposure, and abuse cases.
Logging and observability
- Use structured, meaningful logs.
- Log identifiers needed to investigate a request without exposing sensitive data.
- Use appropriate log levels.
- Do not use
System.outor print stack traces directly. - Avoid duplicate logging of the same exception across multiple layers.
- Preserve exception causes when translating errors.
- Add metrics or tracing for important new workflows when the project already supports them.
Spring Boot testing
- Add unit tests for domain and service logic.
- Use integration tests for persistence, security, serialization, transactions, and framework configuration.
- Prefer focused Spring test slices when the full application context is unnecessary.
- Use the project's established database test strategy.
- Do not depend on test execution order.
- Keep tests deterministic and isolated.
- Test success, validation failure, authorization failure, and important edge cases.
- Add regression tests for bug fixes.
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 for rolling upgrades or backward-compatible deployment until an explicit project decision declares production data must be preserved.
Before finishing
- Review the full diff for unrelated changes.
- Verify that new code follows the existing architecture and naming conventions.
- Check for oversized components, classes, and methods.
- Check for duplicated logic and unnecessary abstractions.
- Run the frontend formatter, linter, type checker, and relevant tests.
- Run the backend formatter or style checks, static analysis, and relevant tests.
- Run the project build when practical.
- Verify API and database changes are reflected in tests and documentation.
- Verify loading, empty, validation, error, and authorization states.
- Confirm that no secrets, debug statements, temporary files, or generated artifacts were added.
- Summarize any command that could not be run and explain why.