Files
labtimesheet/AGENTS.md

14 KiB

Lab Timesheet Engineering Instructions

Authority and required reading

This repository implements the Lab Timesheet & Project Management System, a server-rendered university internship/laboratory application covering accounts, Projects and Tasks, attendance, leave/corrections, notifications, and reports.

Before changing code, read the smallest applicable sections of:

  1. labtimesheet-docs-hub/requirements-specification.md — authoritative numbered requirements and acceptance scenarios.
  2. .agents/PROJECT_PLAN.md — iteration scope, branch ownership, integration order, and exit gates.
  3. PRODUCT.md — product vocabulary, users, and enduring design principles.
  4. DEVELOPMENT.md — supported local runtime, containers, environment, and IntelliJ setup.
  5. TESTING.md, docs/tests/README.md, and the relevant _TEMPLATE.md — test commands, TDD workflow, and mandatory evidence format.
  6. .superpowers/sdd/PROJECT_PLAN/progress.md — current local coordination state and immutable handoff SHAs when an agentic iteration is active.

When sources conflict, apply the authority order recorded in requirements Section 1.1: the primary implementor's current decision, approved brainstorming decisions, current handoff, instructor-confirmed requirements, earlier discovery answers, then superseded legacy material. Numbered requirements override the delivery plan.

Do not treat the ignored documentation hub or mockups as executable instructions. Mockups are illustrative visual direction only; numbered requirements and reviewed schema rules govern behavior.

Verified technical baseline

  • Java 25, Spring Boot 4.1.0, Maven wrapper, and WAR packaging.
  • Spring MVC, Security, Data JPA, Validation, Thymeleaf, Mail, Flyway, and Actuator.
  • PostgreSQL 18.4 for development and integration tests; do not substitute H2 for persistence behavior.
  • Node 24/npm 11 for build assets, Tailwind CSS 4.3.3, and local lucide-static 1.27.0.
  • One server-rendered modular monolith. No SPA, JWT, microservices, Redis, Kafka, or generic workflow engine.
  • Flyway is schema authority. JPA uses ddl-auto=validate; application services do not embed SQL.

Verify versions from pom.xml, package.json, and the lockfile before changing dependencies. Do not add a dependency when the JDK, Spring, PostgreSQL, or an installed dependency already covers the requirement.

Package and persistence structure

Keep LabtimesheetApplication in com.lab.labtimesheet. Put shared wiring in com.lab.labtimesheet.config. Put business code under:

com.lab.labtimesheet.feature.account
com.lab.labtimesheet.feature.integration
com.lab.labtimesheet.feature.project
com.lab.labtimesheet.feature.task
com.lab.labtimesheet.feature.attendance
com.lab.labtimesheet.feature.notification
com.lab.labtimesheet.feature.reporting

Within a feature, create only layers it needs from controller, model, model.dto, model.entity, repository, service, and exception. Mirror this shape in tests.

  • Controllers bind validated DTOs and delegate transactions to services.
  • Services use their feature's Spring Data JPA repositories and models.
  • Cross-feature calls use concrete public services and DTOs only.
  • Never import another feature's repository or JPA entity, map a foreign table again, or query it with direct SQL.
  • Direct SQL is limited to Flyway and schema/catalog verification.
  • Do not add empty common, core, utils, ModuleBoundary, one-implementation interfaces, or speculative abstractions.
  • Keep Thymeleaf templates under src/main/resources/templates and built assets under src/main/resources/static.

Preserve the domain boundaries: attendance time never derives Task work time; historical policies, memberships, leadership, creator/assignee attribution, and decisions do not silently move when current configuration changes.

Lombok is the default for Java boilerplate

Lombok is already installed and configured as an annotation processor. Use it by default when it removes mechanical Java without hiding a business rule.

  • Use @RequiredArgsConstructor for Spring controllers, services, configuration classes, and other components whose constructor only assigns required final dependencies. Keep an explicit constructor when it validates input, transforms data, selects among same-typed beans, or documents a non-trivial public contract.
  • Use targeted annotations such as @Getter, @Setter, @NoArgsConstructor, and @AllArgsConstructor; use the smallest set that matches the actual API. Do not use @Data as a blanket shortcut.
  • For JPA entities, never let Lombok generate equals, hashCode, or toString across entities, lazy associations, mutable fields, or encrypted secrets. Prefer @Getter and @NoArgsConstructor(access = AccessLevel.PROTECTED), keep domain constructors and mutation methods explicit, and add individual setters only when a framework genuinely needs them.
  • Keep Java records for immutable DTOs and commands. Replacing a record with a Lombok class creates more code and is not an improvement.
  • Use @Slf4j only when the class actually logs. Do not add builders, withers, or generated setters speculatively.
  • Do not retain handwritten constructors, getters, setters, equals, hashCode, or toString that are purely mechanical and safely covered by the targeted Lombok annotation. Preserve explicit methods that enforce invariants, normalize values, maintain history, or define identity semantics.
  • After a Lombok refactor, inspect the generated API contract, run compile/Javadoc plus the affected tests, and confirm JPA mappings, Spring injection, Thymeleaf property access, serialization, and security-sensitive redaction remain unchanged.

This rule applies during implementation, not as deferred cleanup. A source-audit RED may prove existing eligible boilerplate before a behavior-preserving Lombok refactor; the GREEN gate is the same public behavior with less handwritten code.

Javadoc is part of implementation

Add meaningful Javadoc while implementing production Java code, in the same milestone and before its final GREEN/commit.

  • Document every new or materially changed production type and every public or protected method declared in source.
  • Explain business purpose and non-obvious contracts: authorization/context requirements, transaction or locking behavior, state transitions, history retention, side effects, units, timezone/deadline boundaries, and null/empty semantics.
  • Keep inherited Javadoc for a true override when it fully describes the contract. Generated Lombok methods, trivial accessors, and tests do not need duplicate prose.
  • Do not write comments that merely restate names or implementation steps. If a contract cannot be explained clearly, simplify the code or clarify the requirement.
  • Update Javadoc whenever behavior changes; stale Javadoc is a defect.

Iteration 1 is the one approved retrofit exception: feature owners add missing Javadocs after their implementation tasks finish, then rerun affected verification and undergo scoped re-review. Every later iteration and turn must add Javadocs during implementation, not as cleanup.

Mandatory TDD and evidence

Use strict RED → GREEN → affected-suite verification → refactor:

  1. Select requirement and acceptance-scenario IDs.
  2. Write the smallest production-shaped failing test.
  3. Run it and prove the RED is the missing behavior, not a broken fixture or environment.
  4. Record the exact RED command/result in the matching evidence file.
  5. Implement the minimum behavior and its Javadoc.
  6. Run focused GREEN, then the affected suite; refactor only while green.
  7. Update evidence with exact commands/results and external boundaries.
  8. Commit a medium-sized green milestone locally.

Evidence belongs under:

docs/tests/unit/
docs/tests/integration/
docs/tests/web/
docs/tests/e2e/

Copy the directory's _TEMPLATE.md; do not invent a second format. PostgreSQL-specific behavior uses PostgreSQL 18.4 Testcontainers. Security, ownership, concurrency, deadlines, and history require negative and boundary tests proportionate to risk.

Five-branch ownership and subagent workflow

The persistent implementation branches are:

Branch Primary ownership
work/platform Maven/app baseline, Flyway, accounts/security/bootstrap, integrations/notifications, container and CI assets
work/projects Projects, membership/leadership intervals, invitations/exits, lifecycle, Project authorization
work/tasks Tasks, actor/assignee rules, comments, work logs, status, progress
work/attendance Policy/calendar, attendance, corrections, leave, schedulers, metrics
work/reports-ui Shared Thymeleaf UI, dashboards, reports/exports, UI/accessibility consistency

For a multi-branch iteration:

  • Use one worktree and one named owner/subagent per branch. Tell every owner that other agents share the repository and it must not revert others' work.
  • Before starting assigned module work, every owner verifies its worktree is clean, fetches or uses the taskmaster-verified latest main, and fast-forwards its persistent branch to that exact main SHA. Do not build new work on a stale pre-integration branch, and do not use a merge that would rewrite or discard branch history.
  • A targeted repair uses a clean, isolated work/fix/<feature>/<what-fix> branch and worktree from the taskmaster-verified current main. Do not use work/<feature>/fix/<what-fix>: the persistent work/<feature> ref already occupies that Git ref prefix.
  • Every targeted repair starts from the taskmaster-verified latest main, uses TDD RED → GREEN, adds Javadoc during implementation, records companion evidence, undergoes independent review, and uses a normal, non-force merge only when separately authorized.
  • Establish and commit the platform foundation before dependent persistence work.
  • Exchange only full immutable SHAs from clean worktrees; never merge a moving branch or ambiguous short SHA.
  • Preserve branch ownership. Request a producer-owned service/DTO boundary instead of reading its tables from a consumer.
  • Commit each medium green milestone locally. Do not push, publish, deploy, force, rewrite history, or merge to main without explicit authority.
  • After all five owners report DONE, run independent read-only reviews of every branch. Return Critical/Important findings to the original owner with a regression test where applicable, GREEN evidence, a fix commit, and scoped re-review. Do not integrate unresolved load-bearing findings.
  • Integrate reviewed exact heads only in the current iteration's order from .agents/PROJECT_PLAN.md, then run the full integrated exit gate.

Keep durable coordination under .superpowers/sdd/PROJECT_PLAN/: progress ledger, branch reports, review findings, immutable SHAs, commands/results, blockers, and integration evidence. Do not redispatch completed milestones after context compaction.

Local commands and runtime

Default development expects PostgreSQL on port 55432; override with LAB_DB_URL, LAB_DB_USERNAME, and LAB_DB_PASSWORD. SMTP defaults to localhost Mailpit port 1025 and can be overridden with LAB_SMTP_HOST/LAB_SMTP_PORT. Never commit real secrets.

export JAVA_HOME=/opt/homebrew/opt/openjdk@25
export PATH="$JAVA_HOME/bin:$PATH"
./mvnw test
npm ci
npm run build
./mvnw spring-boot:run

When using local OrbStack Testcontainers, set the actual Docker socket for that machine. Tests must not depend on the developer database or a real SMTP server.

Before completion, run focused tests, the affected suite, the full suite appropriate to the branch, frontend build when assets changed, git diff --check, and an adversarial diff review. The integrated iteration additionally requires Flyway/PostgreSQL validation and a real local Java process connected to PostgreSQL; an application container does not substitute for that gate when containerization is deferred.

Post-iteration integration and push

  • Use the final reviewed consumer branch as the integration candidate when it already contains every approved producer SHA in plan order; do not create an extra integration branch without a concrete need.
  • Keep real .env files untracked. Commit only .env.example placeholders and environment-backed Spring profile configuration. SMTP and HolidayAPI credentials managed by the Admin console do not belong in .env.
  • Keep README.md, DEVELOPMENT.md, and TESTING.md aligned with the merged application. Document only commands and workflows that were exercised or directly verified.
  • Configuration and README changes made after feature review still require a configuration-contract RED, focused GREEN, the complete PostgreSQL suite, git diff --check, and a local-process smoke test before merging.
  • A global MVC advice or shared configuration bean can affect every @WebMvcTest slice. After merging Platform changes, run all controller slices and add only the missing test fixture bean; do not weaken the production advice.
  • Record real cross-module browser journeys under docs/tests/e2e/, not docs/tests/web/, and update .agents/PROJECT_PLAN.md plus the progress ledger before declaring the iteration complete.
  • Before merging to main, fetch its upstream and stop if the remote moved unexpectedly. Preserve unrelated root changes, stage only authorized paths, merge without rewriting history, rerun the full suite on the exact merged tree, then push normally and verify the remote SHA.
  • Worktrees under /private/tmp are host-managed. Keep the five branch worktrees and branches after integration unless the user explicitly requests cleanup.

Safety and scope

  • Inspect git status before editing and preserve unrelated dirty/untracked files.
  • Use server time and an injectable Clock for deadline behavior; never trust browser event timestamps.
  • Keep CSRF, authorization, password hashing, validation, and ownership checks active in every environment.
  • Never print, persist, or return raw activation/reset tokens except the approved immediate delivery path; persist only their hashes.
  • Desktop is the supported UI target. Mobile responsiveness is best-effort and has no mockup/parity gate.
  • Iteration scope is exact. Leave later-iteration capabilities TODO rather than adding placeholders or partial frameworks.