2 Commits

Author SHA1 Message Date
66d9844836 Merge pull request 'specs' (#2) from feature/s4-gitea-ci into main
All checks were successful
Build, test and publish / verify (push) Successful in 2m6s
Reviewed-on: #2
2026-10-29 21:10:39 +01:00
b0c2f28e13 specs
All checks were successful
Build, test and publish / verify (push) Successful in 1m21s
2026-10-29 19:35:10 +01:00
11 changed files with 839 additions and 51 deletions

View File

@@ -3,7 +3,9 @@
De workflow staat in `.gitea/workflows/build.yaml`. Elke branchpush bouwt en test De workflow staat in `.gitea/workflows/build.yaml`. Elke branchpush bouwt en test
backend en frontend, bouwt twee images en draait Playwright tegen die containers. backend en frontend, bouwt twee images en draait Playwright tegen die containers.
Alleen `main` mag daarna images publiceren. Er vindt geen deployment plaats. Alleen `main` mag daarna images publiceren. Er vindt geen deployment plaats.
Tagpushes en aparte pull-requestevents starten geen extra workflow. Tagpushes en aparte pull-requestevents starten geen extra workflow. Een auteur
kan een branchbuild bewust overslaan met een door Gitea ondersteunde markering,
zoals `[skip ci]`; dit is expliciet toegestaan.
## Java-bronbestanden uitvoeren ## Java-bronbestanden uitvoeren
@@ -92,9 +94,9 @@ Runner en containers moeten de Synology en internetdownloads kunnen bereiken.
Repository: `wanjakrah/agiledancers`, hoofdbranch: `main`. Repository: `wanjakrah/agiledancers`, hoofdbranch: `main`.
Actions staat voor deze repository al aan. Controleer zo nodig op de Synology Actions staat voor deze repository al aan. Controleer zo nodig op de Synology
`app.ini` onder `[actions]` de instelling `ENABLED = true` en de Actions-feature `app.ini` onder `[actions]` de instelling `ENABLED = true` en de Actions-feature
onder repositoryinstellingen. Stel `SKIP_WORKFLOW_STRINGS` leeg in als ook commits met teksten als `[skip ci]` onder repositoryinstellingen. De standaard `SKIP_WORKFLOW_STRINGS`, waaronder `[skip ci]`, mogen blijven staan:
verplicht moeten draaien, zoals de afspraak elke branchpush vereist. bewust overslaan is door de maintainer toegestaan. Iedere gewone branchpush start
Wijzig serverconfiguratie alleen indien nodig. een pipeline. Er hoeft daarvoor geen serverinstelling te worden gewijzigd.
Stel bij repository **Settings → Actions** in: Stel bij repository **Settings → Actions** in:
@@ -129,7 +131,8 @@ runnerregistratietoken naar
tokenwaarden. Voor handmatige inrichting kun je dat registratietoken uit de tokenwaarden. Voor handmatige inrichting kun je dat registratietoken uit de
repository-instellingen halen en in hetzelfde bestand plaatsen. repository-instellingen halen en in hetzelfde bestand plaatsen.
Controleer de artifactretentie op de server: een workflow vraagt veertien dagen De bevestigde Gitea 1.25.4-configuratie heeft geen `[actions]`-sectie: de defaults
zijn negentig dagen voor artifacts en 365 dagen voor logs. Een workflow vraagt veertien dagen
via `retention-days: 14`. Een kortere serverlimiet of het vroegtijdig verwijderen via `retention-days: 14`. Een kortere serverlimiet of het vroegtijdig verwijderen
van workflowruns mag die periode niet inkorten. Artifactretentie geldt voor van workflowruns mag die periode niet inkorten. Artifactretentie geldt voor
testdiagnostiek; gepubliceerde containerimages worden niet automatisch verwijderd. testdiagnostiek; gepubliceerde containerimages worden niet automatisch verwijderd.

View File

@@ -1,8 +1,10 @@
# S4 verification evidence # S4 verification evidence
Date: 2026-10-28. Status: repository implementation and local container verification Updated: 2026-10-29. S4 is **complete**. Main publication/pullback passed in run
passed; Gitea and runner configuration are operational. Main publication is #7. Real registry recovery, rerun and stale-main checks passed against isolated
awaiting approval to merge PR #1. S4 is **not complete**. validation image repositories. Server defaults are confirmed from the maintainer's
configuration report and Gitea 1.25.4 documentation; explicit skip markers are an
accepted exception to branchpush triggering.
## Verified locally ## Verified locally
@@ -51,18 +53,21 @@ Local image IDs (not registry digests):
- Backend: `sha256:bd77a46e3dbdcaea9662d21c608098999fe17dfdf241cd28a24a935f47401f61`. - Backend: `sha256:bd77a46e3dbdcaea9662d21c608098999fe17dfdf241cd28a24a935f47401f61`.
- Frontend: `sha256:ce8e6ab21fb8f9cbee280ac2c4d7b4ca24a30e899a457382f1e45c6baf99dfb6`. - Frontend: `sha256:ce8e6ab21fb8f9cbee280ac2c4d7b4ca24a30e899a457382f1e45c6baf99dfb6`.
## Remaining operational acceptance ## Operational acceptance
- [x] Synology architecture confirmed by the maintainer: `x86_64`, - [x] Synology architecture confirmed by the maintainer: `x86_64`,
`linux/amd64`; repository variable `TARGET_PLATFORM=linux/amd64` configured. `linux/amd64`; repository variable `TARGET_PLATFORM=linux/amd64` configured.
- [x] Activate and verify the Docker Desktop HTTP-registry setting. - [x] Activate and verify the Docker Desktop HTTP-registry setting.
- [x] Repository `REGISTRY_USER`/`REGISTRY_TOKEN` secrets configured using the - [x] Repository `REGISTRY_USER`/`REGISTRY_TOKEN` secrets configured using the
supplied token files. A temporary Docker login with the registry token supplied token files. A temporary Docker login with the registry token
succeeded; actual publication still awaits a main-branch merge. succeeded; actual main publication and pullback are now confirmed below.
- [x] Runner ID 1 (`agiledancers-mini-pc`) registered, service started and - [x] Runner ID 1 (`agiledancers-mini-pc`) registered, service started and
online in Gitea. Real feature/failure jobs ran on this runner. online in Gitea. Real feature/failure jobs ran on this runner.
- [ ] Confirm server settings permit every branchpush (including messages with - [x] The maintainer reports no `[actions]` section in app.ini. Gitea 1.25.4
skip strings) and retain uploaded diagnostic artifacts for fourteen days. therefore uses the documented artifact/log defaults of 90/365 days; the
workflow explicitly requests fourteen days for diagnostic artifacts.
The maintainer accepts intentional `[skip ci]`-style opt-outs. No server
change or SSH access was required.
- [x] [Feature run #1](http://192.168.2.28:3000/wanjakrah/agiledancers/actions/runs/1), - [x] [Feature run #1](http://192.168.2.28:3000/wanjakrah/agiledancers/actions/runs/1),
API run ID 2, commit `74a5aa12377d4a62cdebe1dcd6e8a8e1443b33fb`: succeeded, API run ID 2, commit `74a5aa12377d4a62cdebe1dcd6e8a8e1443b33fb`: succeeded,
two container E2E tests passed, publication skipped. Diagnostic ZIP was two container E2E tests passed, publication skipped. Diagnostic ZIP was
@@ -73,14 +78,16 @@ Local image IDs (not registry digests):
backend test; imagebuild/publication did not run. Diagnostic ZIP was backend test; imagebuild/publication did not run. Diagnostic ZIP was
downloaded and verified (15 files). The probe is absent from the real downloaded and verified (15 files). The probe is absent from the real
featurebranch. featurebranch.
- [ ] Real main run: record URL/run ID, both full-SHA images, successful pullback, - [x] Main run #7 (API run/job ID 8) published both full-SHA images, pulled
registry digests and the two `main` aliases. them back and updated/pulled both `main` aliases; digests are recorded below.
- [ ] Real rerun/partial-publication recovery and stale-main evidence: record - [x] Real publication-code probes against the Synology registry passed:
run IDs and unchanged existing commit digests. partial recovery preserves the first image, reruns preserve both commit
digests, and an older commit cannot move current main aliases. Details and
evidence are recorded below.
The isolated publication tests provide automated control-flow coverage; they do The isolated publication tests provide automated control-flow coverage; they do
not substitute for real authenticated registry/Gitea acceptance runs. No application not substitute for real authenticated registry/Gitea acceptance runs. Application
images have been published and no application has been deployed by this work. images have now been published by main; no application deployment is performed.
Gitea 1.25 does not populate `gitea.run_attempt`; the workflow generates a unique Gitea 1.25 does not populate `gitea.run_attempt`; the workflow generates a unique
@@ -90,21 +97,21 @@ were verified by downloading the run-page archive URLs. This is separate from
artifact availability and does not require a server upgrade. artifact availability and does not require a server upgrade.
## Ready for review; main merge not authorized ## Historical review state before the main merge
[PR #1](http://192.168.2.28:3000/wanjakrah/agiledancers/pulls/1) remains open at [PR #1](http://192.168.2.28:3000/wanjakrah/agiledancers/pulls/1) was initially left open at
the maintainer's explicit request. No main merge or application image publication the maintainer's explicit request. Main merge and publication were postponed at
was performed. that stage; the maintainer has since merged it.
[Feature run #3](http://192.168.2.28:3000/wanjakrah/agiledancers/actions/runs/3), [Feature run #3](http://192.168.2.28:3000/wanjakrah/agiledancers/actions/runs/3),
API run/job ID 4, commit `834584dae06b5976936a5e739871f1164cf81bcd`, succeeded. API run/job ID 4, commit `834584dae06b5976936a5e739871f1164cf81bcd`, succeeded.
The two container E2E tests passed and diagnostics were uploaded as The two container E2E tests passed and diagnostics were uploaded as
`diagnostics-4-20261028164607460012324`, confirming unique attempt names work. `diagnostics-4-20261028164607460012324`, confirming unique attempt names work.
The main branch currently contains only its initial commit. PR #1 therefore Before this merge, main contained only its initial commit. PR #1 therefore
includes the prior application history from `feature/setup` as well as S4. Its includes the prior application history from `feature/setup` as well as S4. Its
scope is documented in the PR description. A main merge needs explicit approval; scope is documented in the PR description. The maintainer subsequently merged that full history. Publication and pullback
only then can real main publication/pullback/rerun acceptance be completed. are confirmed below; the remaining acceptance evidence is still tracked above.
## Java 25 helper migration ## Java 25 helper migration
@@ -113,5 +120,92 @@ CI orchestration, setup and behavior tests now run through `java ci/Ci.java`.
The shell/Python helpers have been removed. The source launcher compiles helper The shell/Python helpers have been removed. The source launcher compiles helper
classes in memory without external dependencies or preview flags. Fifteen Java classes in memory without external dependencies or preview flags. Fifteen Java
behavior tests pass, including JSON/configuration preservation, publication gates, behavior tests pass, including JSON/configuration preservation, publication gates,
partial recovery and process deadlines. A real feature run validates this revision partial recovery and process deadlines. Feature run #6 passed for the Java implementation before the maintainer merged
before updating the existing open PR; no merge to main is authorized. PR #1 into main.
## Main publication confirmed after merge
[Main run #7](http://192.168.2.28:3000/wanjakrah/agiledancers/actions/runs/7), API
run/job ID 8, completed successfully for commit
`2356a31aa612c8b0ce4b386a0a65da6589e23285`.
Downloaded and inspected artifact `diagnostics-8-20261029144539933186842`.
Its verified-commit marker, publication log and digest files confirm publication
and pullback of both commit tags and both moving main aliases:
| Image | Digest for the full-SHA tag and main alias |
| --- | --- |
| `192.168.2.28:3000/wanjakrah/agiledancers-backend` | `sha256:483f4593716f94d1c6a7851519b80399b40600e9e49db5b656abed14b4552e93` |
| `192.168.2.28:3000/wanjakrah/agiledancers-frontend` | `sha256:f9be998187751e13a81cbed809938837a3b80fdbfdd122c2126c9792c4320077` |
This closed the original merge/publication blocker. The remaining acceptance
checks have since been completed as recorded below.
## Final acceptance: recovery, rerun and stale-main protection
Completed on 2026-10-29. These were real command-line publication probes using the
production `Pipeline`/`Commands` implementation against the Synology registry,
not a second full Gitea workflow run. The test adapter redirects Docker write
references to dedicated validation repositories and refuses application-image
pushes. Main-head checks use the actual Gitea API.
The verified images from main run #7 were used as the current source. The older
images came from the previously successful feature run #6. The main commit is
`2356a31aa612c8b0ce4b386a0a65da6589e23285`; the older commit is
`aea792307c5d3be43e17c11db3b9f5845dbd5f14`.
Test repositories:
- `192.168.2.28:3000/wanjakrah/s4-validation-1793286292474-backend`
- `192.168.2.28:3000/wanjakrah/s4-validation-1793286292474-frontend`
Evidence/results:
1. Publication was deliberately stopped after backend publication and before
frontend publication. The operation failed; the backend tag existed and the
frontend tag did not.
2. Recovery published the missing frontend image and retained the backend digest.
3. A repeat publication retained both full-SHA digests and pushed only the two
moving validation aliases. No immutable commit tag was pushed again.
4. The older source images were published to the same isolated repositories.
The real Gitea main-head check detected the newer commit. No moving-alias write
was attempted, and before/after manifest hashes remained identical.
5. Application `main` manifests were compared before and after the probes and
remained unchanged.
The backend and frontend immutable digests match the run #7 digests recorded
above. Manifest comparison hashes for the validation main aliases:
| Alias | Before and after SHA-256 of inspected manifest |
| --- | --- |
| Backend main | `b4438f0d32eae92632e1f3c106ca9c4538c87d61d6feda9e0184dd8749b46d8c` |
| Frontend main | `3d2bebc8da4297c54eebeb43ce0f00e61a61e9216dde27c81f08be69cd6c7335` |
Raw local evidence is retained under `ci/artifacts/s4-final-acceptance/`, including
`results.json`, `partial-publication.log`, `recovery.log`, `rerun.log`,
`confirmed-rerun.log` and `stale-main.log`. The isolated validation images remain
available as acceptance artifacts; they are not deployed application instances.
A temporary registry-login timeout interrupted the first stale-run probe. It
failed visibly and cleaned up temporary login state. Retrying the remaining
checks succeeded; the already-passed recovery/rerun evidence was retained.
## Server configuration closure
The maintainer inspected the Synology-hosted Gitea configuration and confirmed
that `[actions]` is absent. Gitea 1.25.4 defaults are:
- Artifact retention: 90 days by default; the workflow's artifact upload requests
fourteen days explicitly.
- Job log retention: 365 days by default.
- Intentional skip strings such as `[skip ci]` are recognized by default.
The maintainer explicitly approved documenting these skip strings as exceptions:
ordinary branchpushes trigger CI, while an author can intentionally opt out with
an existing supported marker. No Gitea configuration change or broad NAS access
is necessary. This is the agreed interpretation of the trigger criterion.
Sources: [Gitea 1.25 Actions settings](https://docs.gitea.com/1.25/administration/config-cheat-sheet/#actions-actions),
[installed-version defaults](https://github.com/go-gitea/gitea/blob/v1.25.4/modules/setting/actions.go).

View File

@@ -1,4 +1,10 @@
# Specifications # Specifications
Store feature specifications, requirements and agreed design decisions here. Store feature specifications, requirements and agreed design decisions here.
Use descriptive Markdown filenames, for example `school-json-import-export.md`. Use descriptive Markdown filenames, prefixed with a unique S# reference, for example `S1_school-json-import-export.md`.
Each spec-file will get a Status with either the values: NEW, REFINED, IN PROGRESS, IN REVIEW, IMPLEMENTED, REJECTED.
Each spec-file that is refined with the grill-me skill, or manually, will be moved to the refined-folder, and its status-field will be set to REFINED.
When a spec-file gets implemented, at first, the spec-file will be moved to the in_progress-folder, and its status-field will be set to IN_PROGRESS.
When a spec-file is fully implemented, the spec-file will be moved to the in_review-folder, and its status-field will be set to IN_REVIEW.
When a spec-file is reviewed, the spec-file will be moved to the implemented-folder, and its status-field will be set to IMPLEMENTED.
When a spec-file is rejected, the spec-file will be moved to the rejected-folder, and its status-field will be set to REJECTED.

View File

View File

View File

@@ -1,6 +1,6 @@
# S1 — School JSON import and export # S1 — School JSON import and export
Status: agreed after the grill-me review. Status: implemented
## User story ## User story

View File

@@ -1,6 +1,6 @@
# S4 — Build and publish pipelines in Gitea # S4 — Build and publish pipelines in Gitea
Status: IN_PROGRESS Status: IMPLEMENTED
Agreed after the grill-me review; shared understanding confirmed. Agreed after the grill-me review; shared understanding confirmed.
@@ -45,7 +45,8 @@ References:
- Enable Actions as needed at instance and repository level, configure Docker on - Enable Actions as needed at instance and repository level, configure Docker on
the mini-PC, and install, register and configure its runner. the mini-PC, and install, register and configure its runner.
- Build and test both backend and frontend for every push to every branch, - Build and test both backend and frontend for every push to every branch,
including newly created branches. Separate tag and pull-request event workflows including newly created branches, except when the author intentionally uses a
supported skip marker such as `[skip ci]`. Separate tag and pull-request event workflows
are not required; branch pushes also check changes used in pull requests. are not required; branch pushes also check changes used in pull requests.
- Build two runnable Docker images: backend and frontend. - Build two runnable Docker images: backend and frontend.
- Run end-to-end tests against those built containers before publication. - Run end-to-end tests against those built containers before publication.
@@ -68,7 +69,9 @@ References:
## Build and verification behavior ## Build and verification behavior
1. Every branch push runs backend and frontend builds and their existing tests. 1. Every ordinary branch push runs backend and frontend builds and their existing
tests. Explicit Gitea-supported skip markers are an accepted maintainer-approved
opt-out.
2. Backend verification includes the existing unit, integration/system and 2. Backend verification includes the existing unit, integration/system and
architecture tests. Current entry point: `mvn clean verify` using Java 25. architecture tests. Current entry point: `mvn clean verify` using Java 25.
3. Frontend verification uses the lockfile (`npm ci`), unit tests (`npm test`) and 3. Frontend verification uses the lockfile (`npm ci`), unit tests (`npm test`) and
@@ -130,30 +133,31 @@ References:
## Acceptance criteria ## Acceptance criteria
- [ ] A push to any branch, including a new branch, starts a pipeline. - [x] A push to any branch, including a new branch, starts a pipeline, except for
- [ ] Backend and frontend build and all existing tests, including architecture an explicit supported skip marker chosen by the author.
- [x] Backend and frontend build and all existing tests, including architecture
and Playwright end-to-end tests, pass before publication is permitted. and Playwright end-to-end tests, pass before publication is permitted.
- [ ] Every branch builds both Docker images; end-to-end tests exercise those - [x] Every branch builds both Docker images; end-to-end tests exercise those
images through the frontend and its `/api` forwarding. images through the frontend and its `/api` forwarding.
- [ ] A failing build or test fails the pipeline without publishing images. - [x] A failing build or test fails the pipeline without publishing images.
- [ ] A successful feature-branch pipeline publishes no application images. - [x] A successful feature-branch pipeline publishes no application images.
- [ ] A successful `main` pipeline publishes both images to the Synology registry - [x] A successful `main` pipeline publishes both images to the Synology registry
with the full commit SHA; both images can be pulled back. with the full commit SHA; both images can be pulled back.
- [ ] Published commit images are preserved on rerun; partial publication can be - [x] Published commit images are preserved on rerun; partial publication can be
completed without overwriting an existing commit image. completed without overwriting an existing commit image.
- [ ] Moving `main` tags are updated only after both commit images are available, - [x] Moving `main` tags are updated only after both commit images are available,
and an older pipeline cannot move them backwards. and an older pipeline cannot move them backwards.
- [ ] Publication or pull-verification failure makes the pipeline fail, even if - [x] Publication or pull-verification failure makes the pipeline fail, even if
some images have already been uploaded. some images have already been uploaded.
- [ ] Available failure diagnostics are retained for fourteen days, and temporary - [x] Available failure diagnostics are retained for fourteen days, and temporary
test containers are cleaned up on success and failure. test containers are cleaned up on success and failure.
- [ ] The runner operates on the existing mini-PC, with Gitea and the registry on - [x] The runner operates on the existing mini-PC, with Gitea and the registry on
the existing Synology; no additional hardware is needed. the existing Synology; no additional hardware is needed.
- [ ] The single target architecture is established and the images are tested on - [x] The single target architecture is established and the images are tested on
that architecture using the existing hardware. that architecture using the existing hardware.
- [ ] A management guide records setup, external settings, secrets, image usage - [x] A management guide records setup, external settings, secrets, image usage
and recovery, including the need to keep the mini-PC/runner available. and recovery, including the need to keep the mini-PC/runner available.
- [ ] Actual pipeline runs demonstrate successful main-branch publication, - [x] Actual pipeline runs demonstrate successful main-branch publication,
feature-branch checks without publication, and failure blocking publication. feature-branch checks without publication, and failure blocking publication.
## Implementation handoff ## Implementation handoff
@@ -171,8 +175,8 @@ Repository implementation and local Docker verification are available. See
[validation evidence](../../docs/s4-validation.md). [validation evidence](../../docs/s4-validation.md).
Backend verification (20 tests), frontend verification (14 tests), both runtime Backend verification (20 tests), frontend verification (14 tests), both runtime
image builds and both Playwright tests against the containers passed. Eleven image builds and both Playwright tests against the containers passed. Fifteen
isolated CI publication/configuration tests pass. The runner binary and user-service Java CI publication/configuration tests pass. The runner binary and user-service
configuration are installed on the mini-PC. configuration are installed on the mini-PC.
The maintainer confirmed the Synology as `x86_64` / `linux/amd64`. Gitea secrets The maintainer confirmed the Synology as `x86_64` / `linux/amd64`. Gitea secrets
@@ -181,6 +185,16 @@ online. Registry login succeeded. Real feature runs #1 and #3 passed, including
container E2E; deliberate failure run #2 blocked the build/publication path and container E2E; deliberate failure run #2 blocked the build/publication path and
provided downloadable diagnostics. provided downloadable diagnostics.
PR #1 is open. The maintainer explicitly declined merging it for now. Main image PR #1 was subsequently merged by the maintainer. Main run #7 succeeded for
publication, pullback and rerun acceptance therefore remain pending. The spec commit `2356a31aa612c8b0ce4b386a0a65da6589e23285`, publishing and pulling both
stays IN_PROGRESS until those requirements are met. full-SHA images and both main aliases. Registry digests are recorded in the
validation evidence.
The final real-registry probes confirmed partial-publication recovery, immutable
commit-tag preservation on rerun and stale-main protection in isolated validation
repositories. Application manifests remained unchanged. The maintainer confirmed
that the Synology app.ini has no actions section, so Gitea 1.25.4's documented
90-day artifact and 365-day log defaults apply; the workflow requests fourteen
days for diagnostic artifacts. Explicit skip markers are accepted by the
maintainer. All acceptance criteria are met; see the validation evidence for
probe details, digests and the distinction from full Gitea workflow reruns.

View File

@@ -0,0 +1,218 @@
# S2 — ESLint for the frontend
Status: REFINED
Agreed after the grill-me review; shared understanding confirmed.
## User story
As a frontend maintainer, I want automated lint checks during development and in
CI, so that likely bugs and Angular/TypeScript problems are caught before changes
are accepted or application images are published.
I also want a fast local commit hook where feasible, without losing control of
which changes are included in my commit.
## Scope and boundary with S3
### In scope
- Install and configure compatible ESLint, TypeScript and Angular lint tooling.
- Apply the recommended JavaScript, TypeScript and Angular rules, including
recommended type-aware checks for TypeScript.
- Lint maintained frontend application code, external and inline Angular HTML
templates, unit tests, Playwright tests and applicable frontend configuration
files.
- Fix all existing violations of the agreed rules and verify that the application
still builds and its tests pass.
- Provide local check and autofix commands, mandatory pipeline enforcement,
editor support and documentation.
- Introduce a staged-file commit hook only if it meets the agreed performance
and change-preservation requirements.
### Out of scope
- Additional opinionated coding conventions or stricter rule sets beyond the
agreed recommended baseline. These belong in S3.
- Backend or Java CI-helper linting.
- Linting dependencies, generated output or generated files such as
`package-lock.json`.
- A new mandatory Prettier check in CI. Prettier remains the formatting tool;
this spec adds its local commit-hook use only when the timing budget permits.
## Existing environment
The reviewed frontend uses Angular 22.2.3, Angular CLI/build 22.2.4, TypeScript
6.0.3 and Prettier 3.9.10. TypeScript strict mode and Angular strict-template
checking are already enabled. Prettier configuration already exists.
No ESLint configuration, lint command or active Git commit hook was present at
review. The frontend package is in `agiledancers-fe/`, below the Git root.
Implementation must account for that layout when installing repository hooks.
Choose versions compatible with the installed Angular CLI and TypeScript. Use
supported configuration for those versions rather than copying incompatible
examples or changing framework versions merely to introduce linting.
## Lint commands and rule behavior
- `npm run lint`, executed from `agiledancers-fe/`, checks the entire maintained
frontend scope without changing files.
- A lint error or warning causes a nonzero exit status. A successful check means
there are no outstanding ESLint errors or warnings.
- `npm run lint:fix` is an explicit local command that applies supported ESLint
autofixes. Developers review its changes and resolve any remaining findings.
- CI uses the checking command only and must not repair, format, stage or commit
source changes itself.
- Keep formatting under the existing Prettier configuration. Do not introduce
conflicting ESLint formatting rules or redefine formatting conventions in S2.
- Narrow exceptions are permitted when a rule is demonstrably unsuitable. Each
suppression has a concrete explanation and the smallest applicable scope.
Do not broadly disable rules merely to avoid investigating existing findings.
- Start with a clean baseline: do not introduce a legacy-violation allowance,
warning backlog or ignored maintained files to make the initial check pass.
- Fixes preserve application behavior; builds and tests must still pass.
## Pipeline integration
Every branch pipeline must run `npm run lint` immediately after frontend
`npm ci`, before frontend tests, frontend builds and container end-to-end tests.
A failed lint check fails the pipeline and prevents image publication. Its
concrete findings must be visible in the job log and retained in the existing
pipeline diagnostics. The local hook never replaces the full pipeline check.
Integrate this into the existing Java-based pipeline orchestration. Repository
hook installation is skipped during CI and Docker package installation.
## Editor support
Recommend the ESLint extension in the existing VS Code project recommendations.
Do not require automatic fixing or formatting on save. Document how developers
can see findings while editing and run the same check as CI.
## Local commit hook
### File selection and tools
- Only process maintained frontend files staged for the current commit.
- Skip frontend checks for commits without applicable staged frontend changes.
- ESLint only checks; it does not autofix in the hook. Errors and warnings block
the commit if ESLint is part of the selected hook configuration.
- Prettier may format maintained frontend TypeScript, JavaScript, HTML, CSS and
JSON configuration files and stage the formatting result automatically.
- Exclude dependencies, build output and generated files such as
`package-lock.json`.
- If both tools are included, format with Prettier before checking the result
with ESLint. Do not run modifying operations concurrently on overlapping files.
### Preserve the intended commit
- Support partially staged files: format the version intended for the commit
while preserving unrelated unstaged changes.
- Automatically staging formatting must not include unrelated local edits or
change which unrelated files are committed.
- On any hook failure, including an ESLint failure after successful formatting,
abort the commit and restore the original staged and unstaged state.
- A conflict while reconciling formatting with unstaged edits also aborts the
commit and restores the original state.
- Report a concrete cause when the hook fails. Do not leave partial formatter,
staging or temporary-state changes behind.
- Use tooling that supports this behavior with its state-preservation protections
enabled; the specific hook manager/staged-file runner is an implementation
choice.
### Three-second performance budget
The budget covers the entire additional hook duration, including file selection,
backup/state handling, tool startup, formatting/checking, restaging and cleanup.
It is a combined budget, not three seconds per tool.
Measure the actual complete hook on the existing development mini-PC for:
1. A single applicable staged frontend file.
2. A mixed commit containing applicable frontend file types.
3. All maintained frontend files staged together.
Use a newly started process and no tool cache for each measured execution,
including cold tool starts. Every measured execution must finish within three
seconds. Record the machine/environment, exact staged scope, commands and timing
results in the implementation evidence. Do not claim the budget based only on
warm cached executions or timings of an individual tool.
Choose the hook configuration from those measurements:
1. Include Prettier and ESLint if the combined complete hook meets the budget.
2. Otherwise omit ESLint from the hook and measure the complete Prettier-only
hook against the same budget and scenarios.
3. If Prettier-only also fails the budget, do not install an active commit hook.
Do not enforce the budget by killing a writing formatter mid-operation. It is an
acceptance criterion for selecting the hook configuration, not a hard runtime
interrupt that risks incomplete changes. The full type-aware ESLint check remains
mandatory in CI regardless of the selected local hook configuration.
### Installation and operation
If a hook configuration meets the budget, set it up automatically during local
`npm ci`. Skip installation in CI and Docker builds. Document the selected tools,
installation behavior and how a developer can disable the local hook.
If no hook configuration meets the budget, document that result and its timing
evidence. Local lint commands and mandatory pipeline enforcement still apply.
## Documentation
Add an explanation to the root `README.md` for both `npm run lint` and
`npm run lint:fix`, including:
- Run the commands from `agiledancers-fe/`.
- What each command checks or changes and the difference between checking and
autofixing.
- That errors and warnings fail the checking command, and autofix may leave
findings requiring manual changes.
- That the pipeline runs the check and blocks publication on failure.
- The selected hook behavior, its measured performance and any omitted checks.
- Automatic local installation, exclusion from CI/Docker installation, and local
opt-out instructions if a hook is installed.
- Prettier formatting/restaging and preservation of partially staged files,
including restoration on hook failure, when applicable.
The frontend README may link to the root explanation to keep instructions
consistent. Record the performance evidence with the implementation documentation.
## Acceptance criteria
- [ ] Compatible tooling checks maintained application TypeScript/JavaScript,
Angular templates, unit tests, Playwright tests and applicable frontend
configuration using the agreed recommended and type-aware rules.
- [ ] All existing violations are fixed; there is no legacy baseline allowance.
Frontend builds, unit tests and container end-to-end tests still pass.
- [ ] `npm run lint` checks the full scope without modifications and fails on
either errors or warnings.
- [ ] `npm run lint:fix` offers explicit local autofixes; CI does not modify source.
- [ ] Formatting remains under Prettier, without conflicting ESLint rules.
- [ ] Any necessary rule suppressions are narrow and concretely justified.
- [ ] Every branch pipeline runs lint immediately after frontend `npm ci` and
before frontend tests/builds and container E2E; lint failure prevents
publication and leaves actionable diagnostic output.
- [ ] VS Code recommends ESLint without mandatory fix/format-on-save settings.
- [ ] Complete-hook measurements cover the agreed single-file, mixed-file and
all-maintained-files cases with fresh processes and no tool cache.
- [ ] The measured three-second budget determines combined tools, Prettier-only
or no active hook; no writing formatter is forcibly interrupted to meet it.
- [ ] If installed, the hook processes only applicable staged frontend files,
applies Prettier formatting before any ESLint check, and preserves unrelated
files and unstaged edits, including partially staged files.
- [ ] A failed installed hook restores the original staged and unstaged state and
blocks the commit with a concrete explanation.
- [ ] Hook installation is automatic for local `npm ci` when applicable, skipped
in CI/Docker, and has documented local opt-out instructions.
- [ ] Root `README.md` explains `npm run lint`, `npm run lint:fix`, CI enforcement
and the selected hook behavior; measurement evidence is included.
## Implementation handoff
This specification records agreed behavior. It does not install ESLint, change
application code, modify the pipeline, install a hook or update command usage in
the README yet. Those changes and the timing measurements are implementation work.

View File

@@ -0,0 +1,255 @@
# S5 — Renovate bot in a container
Status: REFINED
Agreed after the grill-me review; shared understanding confirmed.
## User story
As a developer, I want a containerized Renovate bot to check the repositories on
our Gitea server and propose dependency updates through pull requests, so that
frontend, backend and build infrastructure dependencies remain maintainable and
we reduce risks from outdated versions.
I want external release age and project compatibility to constrain those
proposals. I retain control over merging and can upgrade dependencies manually
when I deliberately choose to act outside the bot's waiting period.
## Environment and scope
- Gitea and its container registry run on the existing Synology. Renovate runs in
a container on that same Synology; no additional hardware is required.
- The established Synology target platform is `linux/amd64`.
- Discover all repositories on this Gitea instance for which the dedicated bot
account has the necessary access. Support explicit repository exclusions.
- Before dependency PRs are proposed for a newly discovered repository, create an
onboarding/configuration PR. A maintainer must approve and merge that
configuration first.
- This project contains a `renovate.json` with its agreed compatibility and update
boundaries. Other onboarded repositories have their own reviewed configuration.
- Use a dedicated bot account/token with the access required for repository
discovery, branches, PRs, dashboards and dependency metadata lookup. Keep
credential values outside Git and logs.
### Dependency surfaces
Cover supported maintained dependency declarations, including:
- Frontend dependencies and development dependencies, compilers and test tools.
- Backend dependencies, Maven parents/BOMs, plugins and version properties.
- Docker base images and maintained container-image references.
- Pinned workflow actions, including version/digest references.
- The Renovate container's own version declaration.
- Related lockfile changes and separate lockfile maintenance.
Detection must include relevant maintained references outside ordinary manifests,
for example the Playwright image reference in the Java CI helper. Where related
references must match, update and validate them together. The Playwright package
and browser image must stay aligned.
One explicit manual boundary remains: the runner binary download version and its
binary SHA-256 checksum in the CI setup helper are maintained manually. Document
this boundary. Do not generate a partial runner update, leave an obsolete
checksum, or confuse a Git commit SHA with the binary's SHA-256.
Unsupported dependency references or missing required metadata must be visible as
limitations/blockers, rather than silently counted as successfully managed.
## Schedule and execution
- Run daily at **06:00 in `Europe/Amsterdam`**. The schedule/timezone are
configurable and the default is recorded in the deployment configuration.
- Provide the actual scheduler/container setup on the Synology; adding an image
declaration alone does not make the periodic execution operational.
- The Synology can perform dependency checks while the development mini-PC is
off. Project CI jobs still depend on their existing runner availability.
- The daily run can discover candidates, maintain eligible PRs and propose new
eligible updates within the agreed limits. It does not merge updates.
## Seven-day release-age policy
### Universal bot policy
- A release must be at least **seven days old** before Renovate proposes that
version in a dependency PR.
- Apply this to all bot-proposed dependency updates, including internal libraries,
security updates, infrastructure dependencies and the bot's own image update.
There is no internal-library or security-update exception.
- Apply the same check when an existing PR is updated to a newer version. An
existing eligible PR must not gain an ineligible new version through refresh.
- Missing or unreliable release timestamps block the affected proposal until its
age is demonstrable. Do not treat missing metadata as proof of sufficient age.
- Show the concrete blocker in the repository dashboard, with useful diagnostics.
A dependent/coherent update group cannot be partially proposed in an invalid
combination to work around an age blocker.
- Enforce the policy centrally across onboarded repositories. Repository-local
configuration, security-update defaults or bot retry/approval mechanisms must
not silently relax the waiting period or timestamp requirement.
- A maintainer may choose to upgrade earlier **manually**, outside Renovate. That
does not authorize Renovate to bypass its policy.
### Lockfiles and transitives
The waiting period also applies to newly introduced or changed transitive
versions in bot-generated lockfile changes. Determine those changes relative to
the repository base revision used by the proposal.
- Validate the age of those versions before the PR is created or updated.
- Unknown ages block the affected proposal, just as they do for direct updates.
- Existing unchanged versions in the base revision are not newly introduced by
the bot; the policy is not a requirement to rewrite all historical lock entries.
- Additional validation is part of S5 where Renovate's native behavior cannot
establish this guarantee. Do not assume a package-manager cutoff covers every
fallback path.
- A failing validator must actually prevent PR creation/update. A command that
fails but only adds an artifact error or failed status to an already-created
ineligible PR does not satisfy this requirement.
### Metadata limitations
Not every datasource/registry supplies usable release timestamps. This includes
some container-image sources. Such updates remain blocked and visible unless
reliable metadata support is implemented and validated; manual maintenance is
possible outside the bot.
For example, the npm release timestamp of Playwright is not proof of the release
age of its separately published container image. Both references must satisfy
applicable policy before their coordinated bot proposal is offered.
## Compatibility and upgrade boundaries
### Project-owned boundaries
- The official Angular compatibility table is the reference for Angular's Node.js,
TypeScript and RxJS compatibility: <https://angular.dev/reference/versions>.
- Project maintainers encode and maintain the applicable ranges in
`renovate.json`, including supported Node majors and TypeScript minor ranges.
- Renovate must stay within those explicit ranges and must not independently
widen the policy to make a proposed version eligible.
- Boundaries must reflect the actual installed framework/tooling metadata where
relevant. Remaining in the same dependency major is not sufficient if Angular
requires a narrower range.
- Node.js, TypeScript and RxJS updates, including major updates, may be proposed
when the explicit project boundaries allow them and they remain compatible with
the project's Angular version.
### Angular upgrades
- Angular major upgrades are performed manually through a separate specification.
- Libraries/tooling whose major numbering follows Angular are upgraded to a new
major with Angular, also through that manual specification.
- Renovate proposes only minor and patch updates for Angular and that aligned
family, maintaining a coherent compatible combination.
- Runtime/compiler dependencies that require matching versions stay aligned.
Do not assume unrelated Angular tooling repositories must all have identical
patch numbers merely because their majors align.
- Group related changes where necessary to preserve compatibility. TypeScript and
RxJS proposals still obey their own explicit allowed ranges.
### Declared versions versus installed software
Maintain coherent repository declarations where a dependency appears in multiple
places, such as Node requirements in manifests, version files, Docker definitions
and setup checks. A bot PR does not install a new Node version on the mini-PC or
replace a running container. Those are documented manual management actions.
## Branches, PRs and limits
- Use the branch prefix `renovate/`.
- Use `renovate/major/<dependency-or-group>` for eligible major updates.
- Use `renovate/minor-patch/<dependency-or-group>` for eligible minor/patch updates.
- Each independent dependency has its own update PR. Related packages from one
upstream project may be grouped to maintain a coherent update.
- Keep major-update proposals separate from minor/patch proposals. Necessary
companion changes belong with the coherent upgrade they support; unrelated
smaller updates are not mixed into a major PR.
- Maintain at most **five open dependency PRs per repository**, including the
separate lockfile-maintenance PR when one exists.
- Queue additional eligible updates for a later daily round after slots become
available. There is no dynamic sixth/seventh overflow PR or custom overflow
bundling requirement.
- Onboarding/configuration PRs are outside this dependency-PR limit and precede
ordinary dependency proposals.
- Renovate creates and updates proposals only. Maintainers review the change and
CI result and merge manually; automerge is disabled.
## Lockfile maintenance
- Ordinary manifest updates include the matching lockfile changes in the same
PR, so reproducible installation remains valid.
- Separately maintain lockfiles within the existing manifest boundaries on a
branch such as `renovate/minor-patch/lockfile-maintenance`.
- Keep that maintenance PR separate from ordinary dependency-update PRs and count
it within the five-PR limit.
- Apply the same seven-day checks to newly resolved/changed versions in that PR.
- Do not split a normal manifest update from the lockfile required by that update
into separately mergeable, inconsistent proposals.
## Maintaining existing PRs
During daily execution, Renovate may refresh existing bot proposals and rebase
them when the base branch changes. Refreshed candidates must again pass age and
compatibility checks.
Do not overwrite manual changes on bot branches. If manual edits or conflicts
prevent safe maintenance, preserve those edits and show that maintainer action is
required in the dashboard.
## Visibility and management
- Provide a Dependency Dashboard issue per onboarded repository for pending,
open and blocked updates and relevant failures.
- Explain age, missing metadata and compatibility blockers concretely.
- Preserve execution logs and the result of each scheduled run for **thirty days**,
with rotation/retention configured and secret values omitted/redacted.
- Retain operational failure information on the Synology even if startup or Gitea
connectivity fails before repository processing can update a dashboard.
- Provide a management guide covering bot access and secret locations, repository
discovery/exclusions and onboarding, schedule/timezone, manual execution,
dashboards/logs, configuration validation and recovery.
- Document project compatibility maintenance, the manual runner version/checksum
boundary, blocked unsupported metadata, manual host/runtime updates and applying
an approved Renovate-image version to the running installation.
## Acceptance criteria
- [ ] A working Renovate container and daily 06:00 Europe/Amsterdam schedule run
on the existing linux/amd64 Synology.
- [ ] Discovery covers authorized Gitea repositories, respects exclusions and
requires onboarding/configuration approval before dependency proposals.
- [ ] This project has a reviewed `renovate.json` with explicit framework and
dependency boundaries; compatible managed dependency surfaces are detected.
- [ ] Direct, security and new/changed transitive lockfile versions younger than
seven days cannot enter new or refreshed bot PRs.
- [ ] Unknown release ages block proposals visibly; internal dependencies do not
bypass the waiting period.
- [ ] Validation proves repository overrides, security defaults and error/fallback
paths cannot create or update an ineligible PR.
- [ ] Node.js, TypeScript and RxJS updates stay inside the maintainer-controlled
Angular compatibility bounds, including any permitted major upgrades.
- [ ] Angular and Angular-major-aligned library major upgrades are not proposed;
compatible minor/patch changes and coupled package/image references remain
coherent.
- [ ] Independent proposals and permitted coherent groups use the agreed
renovate/major/... and renovate/minor-patch/... branch conventions.
- [ ] Major proposals remain separate from unrelated minor/patch updates.
- [ ] No more than five dependency PRs are open per repository, including lockfile
maintenance; remaining candidates wait rather than form overflow PRs.
- [ ] Normal manifest PRs include matching lockfiles; separate lockfile maintenance
stays within manifest ranges and satisfies the same age policy.
- [ ] Daily maintenance preserves manual branch edits and reports conflicts;
merging and actual host/container upgrades remain manual.
- [ ] The runner binary version/checksum is explicitly documented as manual, with
no partial or incorrect automated checksum updates.
- [ ] Dashboards expose repository-level state; thirty-day logs also expose
failures before repository processing without disclosing secrets.
- [ ] Management documentation and real execution/PR evidence demonstrate the
operational setup and enforcement. Configuration files alone are insufficient.
## Implementation handoff
This specification records agreed behavior. It does not create the bot account,
configure credentials, deploy a container, install a schedule or create PRs/issues.
Those actions, any necessary additional age validation and the operational evidence
are implementation work. S5 is complete only when its behavior has been proven on
the working installation.

View File

@@ -0,0 +1,198 @@
# S8 — Palantir formatting for Java
Status: REFINED
Agreed after the grill-me review; shared understanding confirmed.
## User story
As a developer, I want maintained Java code formatted using Palantir Java Format
through the Maven workflow, so that local development and CI use consistent,
reproducible formatting without unnecessary build overhead.
## Scope
### In scope
- Backend Java production code and Java tests.
- Maintained Java CI/source-launcher helpers under `ci/`, despite those files
being outside ordinary Maven source roots.
- Integration with local Maven builds, CI checking and standalone format/check
commands.
- A separate initial formatting commit, performance measurements and README
instructions.
### Out of scope
- Generated code and build output.
- Frontend formatting, which remains under Prettier.
- Additional coding conventions, naming rules, structural checks or refactorings.
Those belong in S7.
## Formatter and integration
- Use the **actual Palantir Java Format engine** and its Palantir style.
- OpenRewrite is the preferred integration route. S8 includes the custom
Palantir adapter/recipe and bootstrap required to make that route work.
- OpenRewrite's own `AutoFormat` is not an equivalent replacement for Palantir
and must not be substituted silently.
- Spotless is not the agreed default: the maintainer has experienced unacceptable
slowness with it. Do not choose it merely because a native integration exists.
- Pin the formatter, plugin and adapter dependencies to explicit versions in
Maven configuration. Local development and CI use the same pinned engine.
- Formatter/integration updates are reviewed through PRs and include any resulting
formatting changes. Do not implicitly resolve the newest formatter at build time.
- Include Palantir's import ordering and unused-import removal. Do not add
separate import policies or unrelated code transformations.
- Leave optional extra Javadoc reformatting disabled for the initial adoption.
## Maven behavior
### Local builds
Local builds apply formatting before compilation, so the compiled and tested
sources are the formatted sources. Early lifecycle integration means ordinary
`mvn compile`, `mvn test`, `mvn verify` and `mvn install` may format maintained
Java files.
Binding only to `install` does not satisfy this specification: the existing CI
verification uses `mvn clean verify` and would not reach that phase.
Provide standalone commands to:
- Apply formatting without performing the complete application build.
- Check formatting without modifying maintained sources or performing the complete
application build.
The concrete commands/profile names are implementation work and must be documented.
### CI
- CI runs the check-only mode before compilation and fails if formatting differs
from the committed source.
- CI must not repair or rewrite maintained Java source files automatically.
- Use the same pinned Palantir engine, configuration and file scope locally and
in CI; only apply versus check behavior differs.
- Integrate the checking invocation into the existing Java-based CI orchestration.
- Show actionable diagnostics identifying the files that need formatting and how
to apply the formatter locally.
- A formatting failure prevents successful verification and image publication.
Demonstrate that the check leaves maintained source files unchanged on failure.
## Clean-checkout bootstrap
Normal Maven commands from the repository root must work from a clean checkout
without first requiring a developer to compile or install a custom recipe artifact
by hand.
The custom recipe/adapter must be available before it is needed to format the
application sources. Placing it in ordinary backend source code and assuming that
it has already been compiled is not a valid bootstrap solution.
Prove bootstrap behavior with no previously installed project-specific recipe
artifact. Normal dependency resolution is allowed; any extra tooling module or
bootstrap must be included in the implementation and documentation.
## Correctness and Java 25
- Demonstrate support for every Java construct actually used in the maintained
backend, tests and CI helpers on the project's JDK 25.
- Running the formatter on JDK 25 is not, by itself, proof that its parser supports
every possible Java 25 construct. Record relevant limitations of the chosen
pinned version.
- An unprocessable file or formatter error fails the operation/build with its
path and a concrete cause. Do not silently skip it or exclude it merely to
obtain a successful build or faster measurement.
- The adapter must preserve source paths and encoding and avoid corrupting files.
- Formatting is deterministic and idempotent: applying it again produces no
further source differences. Check-only and apply mode agree on the result.
- Application behavior remains unchanged; builds and tests must pass after the
initial formatting and subsequent formatter changes.
## Initial adoption and commit separation
Apply the chosen formatting to all existing maintained Java files in scope.
Record this initial mass formatting in a separate **formatting-only commit**,
without functional changes. Keep integration/configuration changes separate so
reviewers can distinguish tooling changes from the mechanical source rewrite.
Native import ordering/removal is part of that formatting commit. Do not combine
it with unrelated cleanup or refactoring.
## Performance requirements
The integration must be measured rather than selected on an unverified claim that
one wrapper is faster than another.
- A repeated ordinary build with no Java-source changes may incur at most
**three seconds of additional formatting-related overhead**.
- Include the required integration/recipe/bootstrap overhead in that comparison;
do not report only time spent inside the Palantir formatting function.
- Compare otherwise equivalent builds with and without the formatting integration
under the same environment/cache conditions.
- Also measure a build after changing a maintained Java file and a `clean verify`
run. Record these timings; the agreed three-second threshold specifically
applies to the repeated unchanged-build case.
- Report one-time dependency downloads separately, rather than disguising ongoing
overhead as first-time setup or counting downloads as formatter execution.
- Record the machine, JDK/Maven/tool versions, commands, file scope, cache state
and results with the implementation evidence.
The time threshold is an acceptance criterion, not a hard interrupt that kills a
formatter while it is writing source files. If the selected integration cannot
meet the threshold, report the measurements and obtain agreement before choosing
an alternative integration or relaxing the bound. Do not silently skip formatting,
switch engines, choose Spotless or weaken the criterion.
## README and editor integration
Explain in the root `README.md`:
- The formatter, pinned versions/configuration and maintained file scope.
- The standalone apply and check commands.
- Which local Maven lifecycle commands can rewrite files and when that occurs.
- The CI check-only invocation and how to reproduce and resolve a failure locally.
- Clean-checkout bootstrap behavior and any included tooling artifact/module.
- Available supported IDE integration and how to keep its result consistent with
the project's pinned formatter.
- The performance evidence and any relevant Java 25 syntax limitations.
Maven is the authoritative formatting path regardless of editor. Do not require
format-on-save or an IDE plugin. An IDE integration must not redefine the agreed
style or silently take precedence over the Maven result.
## Acceptance criteria
- [ ] The actual Palantir engine formats all maintained backend Java sources,
Java tests and `ci/*.java`; generated code is excluded.
- [ ] OpenRewrite integration, custom adapter/recipe and bootstrap are implemented
and reproducible from a clean checkout without manual recipe installation.
- [ ] Plugin, formatter and adapter dependencies are pinned, with matching local
and CI configuration.
- [ ] Local Maven builds apply formatting before compilation; `compile`, `test`,
`verify` and `install` reach the intended integration.
- [ ] Standalone apply and check commands work without the full application build.
- [ ] CI checks only, leaves maintained sources unchanged, reports formatting
differences and fails before image publication.
- [ ] Import ordering and unused-import removal follow Palantir; optional extra
Javadoc reformatting remains disabled and no unrelated refactoring is added.
- [ ] All currently used Java 25 syntax is handled, or causes an explicit failure
requiring resolution rather than silent exclusion.
- [ ] Apply/check results agree and a second apply produces no differences.
- [ ] Initial formatting is isolated in a formatting-only commit; application
builds and tests remain green.
- [ ] Equivalent repeated unchanged-build measurements demonstrate at most three
seconds of additional integration overhead. Changed-file and clean-build
measurements and one-time downloads are reported separately.
- [ ] Failure to meet the performance bound is reported before changing the route
or bound; a writing formatter is not killed to force compliance.
- [ ] README instructions cover local and CI commands, bootstrap, optional IDE
use, authoritative Maven formatting and verification evidence.
## Implementation handoff
This specification records agreed behavior. It does not install a formatter,
create an adapter, change Maven/CI behavior or reformat source files. Recipe loading,
Java 25 compatibility and performance must be demonstrated during implementation;
there is no pre-existing project benchmark establishing the preferred route's
performance.