S19: consume versioned engineering resources and move landscape documentation
All checks were successful
Build, test and publish / verify (push) Successful in 8m54s

This commit is contained in:
2026-11-08 15:23:10 +01:00
parent bd898e92d2
commit c6a495a93c
100 changed files with 1869 additions and 4274 deletions

View File

@@ -0,0 +1,3 @@
# S19 resource ownership
The complete [migration inventory](http://192.168.2.28:3000/wanjakrah/landscape/src/branch/main/S19-classification.md) records every source resource and its destination.

36
docs/S19-validation.md Normal file
View File

@@ -0,0 +1,36 @@
# S19 validation
The [landscape specification](http://192.168.2.28:3000/wanjakrah/landscape/src/branch/main/specs/S19.md)
and [resource inventory](http://192.168.2.28:3000/wanjakrah/landscape/src/branch/main/S19-classification.md)
describe the repository split. Engineering owns the shared source; this project
consumes its selected tag and commit through engineering.lock.json.
Validated on 2026-11-08:
- Full Maven verification: 73 backend tests and 19 standards regression tests.
Existing approved waiver retained; no new waiver or threshold change.
- Full shared pipeline: frontend lint/build, 32 frontend tests, 4 Playwright
tests, both prebuilt Docker images and combined backend coverage
1771/1841 (96.20%).
- Standalone backend and frontend Docker source builds passed. The backend used
a disposable PostgreSQL container and BuildKit secrets for test configuration.
- Shared CI/release regression suites: 19 and 34 tests respectively.
- Engineering bootstrap/generator suite: 7 tests, covering all component choices,
actual Maven regeneration with generated/ absent, drift including new files,
obsolete-file removal, moved tags and preservation of project-owned files.
- Formatter integration checks passed. Upstream skills and attribution files
match their source snapshot byte for byte; only the skills index was adapted.
- A separate generated example passed its common pipeline and a real isolated
deployment of two synthetic revisions followed by rollback. Production was
not used. See engineering's VALIDATION.md and tests/acceptance.py.
Gitea build-run evidence for the migrated application commit is recorded with
S19 in landscape. Its workflow checks the pinned release before invoking the
same shared pipeline. Checkout and committed generated resources require no
sibling repository checkout.
Production deployment is a separate action. Live NAS SSH authentication,
production credentials and rollback against pre-S19 retained releases were not
exercised. The existing Compose project, database volume and release-state schema
remain compatible. Legacy releases without retained health.sh use the current
application health function; review that compatibility before production rollback.

View File

@@ -1,19 +1,10 @@
# Backend review companion
# Agile Dancers backend review companion
Use alongside `skills/code-review/SKILL.md` and `CODING_STANDARDS.md`.
Use [the shared review guidance](../generated/docs/backend-review.md),
[code-review skill](../generated/skills/code-review/SKILL.md), and
[project standards](../CODING_STANDARDS.md).
Review changed code for intent-revealing comments, missing public-contract Javadoc,
appropriate record use, defensive copying of mutable record components, and
compatibility with APIs, JSON and persistence. Assess ambiguous `var` initializers
and framework/lifecycle exceptions to field finality. Confirm architecture and
injection decisions make sense for production and tests. Check NIO API preference,
varargs for trailing array parameters, and Java 25 IO use for direct console
input/output; retain System.err for diagnostics. Require Javadoc for public
classes and methods beyond basic POJO/data-carrier behavior.
Read standards reports even when verification passes. Assess every review signal
in changed code, including fan-out, public methods and record component counts.
Record a rationale for retained signals in the S7 evidence or change description.
Check narrowly scoped waivers against recorded maintainer agreement and reason.
Never introduce blanket exclusions or weaken thresholds to pass a build.
Do not repeat mechanical checks already enforced by tooling; verify their result.
The backend module is agiledancers-be. The approved Group constructor waiver
remains application-owned in tooling/standards/waivers.tsv. Assess retained
signals against the implementation evidence in docs/validation and the change
description. S19 introduces no standards waiver.

View File

@@ -12,7 +12,7 @@ zoals `[skip ci]`; dit is expliciet toegestaan.
## Java-bronbestanden uitvoeren
De CI- en setuphulpmiddelen zijn Java 25-bronbestanden. Start ze direct met
`java ci/Ci.java <opdracht>` vanuit de repositoryroot. De Java-launcher compileert
`java generated/ci/Ci.java <opdracht>` vanuit de repositoryroot. De Java-launcher compileert
de benodigde bronbestanden in het geheugen. Er is geen aparte `javac`-stap,
Maven-module, Python-installatie of scriptingframework nodig. De helper gebruikt
alleen de JDK, inclusief de HTTP-client, process builder en bestandsloten.
@@ -76,7 +76,7 @@ Je kunt de instelling ook samenvoegen met behoud van bestaande instellingen en
backup via:
```sh
java ci/Ci.java configure-docker "$HOME/.docker/daemon.json"
java generated/ci/Ci.java configure-docker "$HOME/.docker/daemon.json"
```
Voor Docker Engine op Linux is dat dezelfde toevoeging aan
@@ -112,7 +112,7 @@ Het gewone jobtoken van Gitea 1.25 biedt geen packagepublicatie; gebruik een PAT
Gebruik een repository-runnerregistratietoken, geen instancebrede registratie.
Sla tokenwaarden buiten Git op en plaats ze niet in opdrachten, screenshots of logs.
Voor reproduceerbare configuratie bestaat `java ci/Ci.java configure-gitea`. Maak twee
Voor reproduceerbare configuratie bestaat `java generated/ci/Ci.java configure-gitea`. Maak twee
bestanden buiten de repository met mode `600`: één voor een PAT met voldoende
repositorybeheerrechten (repository Actions, secrets, variabelen en runnerregistratie),
en één voor de publicatie-PAT. De beheer-PAT hoeft niet als workflowsecret te worden
@@ -124,7 +124,7 @@ export GITEA_ADMIN_TOKEN_FILE="$HOME/.config/agiledancers-runner/admin-token"
export REGISTRY_TOKEN_FILE="$HOME/.config/agiledancers-runner/registry-token"
export REGISTRY_USER=wanjakrah
export TARGET_PLATFORM=linux/amd64 # alleen als dit op de Synology is vastgesteld
java ci/Ci.java configure-gitea
java generated/ci/Ci.java configure-gitea
```
Het script stelt de repository-instellingen in via de API en schrijft het
@@ -143,9 +143,9 @@ testdiagnostiek; gepubliceerde containerimages worden niet automatisch verwijder
```sh
export JAVA_HOME=/usr/lib/jvm/java-25-openjdk-amd64
java ci/Ci.java install-runner --prepare-only
java generated/ci/Ci.java install-runner --prepare-only
# Na Dockerconfiguratie en het opslaan van het registratietoken:
java ci/Ci.java install-runner
java generated/ci/Ci.java install-runner
systemctl --user status agiledancers-runner
journalctl --user -u agiledancers-runner -f
```
@@ -200,8 +200,8 @@ De frontend luistert op containerpoort 8080, ondersteunt SPA-routes en proxy't
8080. Voorbeelden voor eventueel handmatig starten staan los van de pipeline;
de pipeline start geen blijvende applicatie op de NAS.
`java ci/Ci.java verify` maakt een succesmarker pas na alle builds en tests.
`java ci/Ci.java publish` vereist die marker en hoofdbranchref. Onder een gedeeld Java-bestandslot (`FileChannel`)
`java generated/ci/Ci.java verify` maakt een succesmarker pas na alle builds en tests.
`java generated/ci/Ci.java publish` vereist die marker en hoofdbranchref. Onder een gedeeld Java-bestandslot (`FileChannel`)
buiten de checkout worden bestaande commitimages hergebruikt en ontbrekende
images geüpload. Iedere image wordt teruggehaald, op revisielabel gecontroleerd en
met digest vastgelegd in de diagnostiek. Authenticatie- of netwerkfouten tellen
@@ -238,7 +238,7 @@ blijven de committags bruikbaar en worden de oude `main`-updates overgeslagen.
Lokale controle van publicatie-/foutgedrag zonder registrywijzigingen:
```sh
java ci/Ci.java test
java generated/ci/Ci.java test
```
Volledige lokale verificatie met Docker en de vastgestelde platformwaarde:
@@ -246,7 +246,7 @@ Volledige lokale verificatie met Docker en de vastgestelde platformwaarde:
```sh
export JAVA_HOME=/usr/lib/jvm/java-25-openjdk-amd64
export TARGET_PLATFORM=linux/amd64 # eerst de Synology controleren
java ci/Ci.java verify
java generated/ci/Ci.java verify
```
## Operationele oplevering

View File

@@ -136,8 +136,9 @@ sudo -n /usr/local/bin/docker compose version
sudo -n /usr/local/bin/docker info --format '{{.OSType}}/{{.Architecture}}'
```
Als DSM geen `visudo` bevat, is `deploy/enable-docker.sh` het eenmalige alternatief.
Kopieer het naar de eigen NAS-thuismap en voer het daar met sudo uit. Het maakt
Als DSM geen `visudo` bevat, is `generated/deploy/enable-docker.sh` het eenmalige alternatief.
Kopieer het naar de eigen NAS-thuismap en voer daar
`sudo sh enable-docker.sh agiledancers-deploy /usr/local/bin/docker` uit. Het maakt
uitsluitend de bovengenoemde regel, controleert die door als deploymentaccount
Docker te starten en verwijdert een nieuwe regel als die controle faalt. Een
afwijkende bestaande regel wordt niet overschreven. De implementatiesessie heeft
@@ -177,7 +178,7 @@ inrichten. Bewaar `admin-token`, `s6-release-token`, `s6-pull-token` en de priva
`~/.ssh/known_hosts` en voer uit:
```sh
java ci/Ci.java configure-deployment
java generated/ci/Ci.java configure-deployment
```
Defaults zijn de bevestigde NAS/account/SSH-poort, repository
@@ -269,8 +270,9 @@ nieuwe release door te drukken.
controlescript uitvoeren met bestaande lockowner en gekozen release-directory:
```sh
ssh -i <private-key-path> -p <ssh-port> <deploy-user>@<nas> \
'timeout -k 5 300 sh -s -- apply <production-directory> <lock-owner> <release-directory-id>' < deploy/remote.sh
cat deploy/health.sh generated/deploy/remote.sh | \
ssh -i <private-key-path> -p <ssh-port> <deploy-user>@<nas> \
'COMPOSE_PROJECT=agiledancers-production DEPLOY_ROLES="backend frontend" DEPENDENCY_SERVICES=database REQUIRED_SECRETS=DATABASE_PASSWORD TARGET_PLATFORM=linux/amd64 timeout -k 5 300 sh -s -- apply <production-directory> <lock-owner> <release-directory-id>'
```
Gebruik de eerder gepinde hostkey en gecontroleerde waarden uit het journal.
@@ -294,9 +296,9 @@ apart: imageherstel maakt geen migratie ongedaan. Rollback naar een oude release
van vóór S16 kan de database niet lezen. Backup/restore blijven S17-werk.
```sh
java ci/Ci.java test
java ci/Ci.java release-test
sh -n deploy/remote.sh
java generated/ci/Ci.java test
java generated/ci/Ci.java release-test
sh -n generated/deploy/remote.sh
mvn -N -Dformat.mode=check exec:exec@format
```

View File

@@ -1,3 +1,5 @@
> Historical validation evidence from application commit `bd898e92d22f6c412e671908770f4d89c8ae12bc`. Commands retain their original paths; current tooling is documented in README.md.
# S18 implementation validation
Validated on 2026-11-03 against the confirmed S18 specification.

View File

@@ -1,3 +1,5 @@
> Historical validation evidence from application commit `bd898e92d22f6c412e671908770f4d89c8ae12bc`. Commands retain their original paths; current tooling is documented in README.md.
# S2 implementation evidence
Validated on the development mini-PC on 2026-10-29: AMD Ryzen 7 7730U (8 cores,
@@ -58,7 +60,7 @@ Prettier. The selected configuration uses only Prettier. Staged scopes are:
- All: all 52 maintained frontend files, including non-applicable files that the
hook must skip, plus a small TS preservation-test fixture; generated lockfile
excluded. Exact paths and raw measurements are in
[the timing report](s2-hook-timings.json).
[the timing report](http://192.168.2.28:3000/wanjakrah/agiledancers/src/commit/bd898e92d22f6c412e671908770f4d89c8ae12bc/docs/s2-hook-timings.json).
| Candidate | Staged scope | Run 1 | Run 2 | Run 3 |
| --- | --- | --- | --- | --- |

View File

@@ -1,3 +1,5 @@
> Historical validation evidence from application commit `bd898e92d22f6c412e671908770f4d89c8ae12bc`. Commands retain their original paths; current tooling is documented in README.md.
# S4 verification evidence
Updated: 2026-10-29. S4 is **complete**. Main publication/pullback passed in run

View File

@@ -1,3 +1,5 @@
> Historical validation evidence from application commit `bd898e92d22f6c412e671908770f4d89c8ae12bc`. Commands retain their original paths; current tooling is documented in README.md.
# S6 implementation and operational evidence
Status: IN_REVIEW. Production `v1.0.0` is running on the Synology at

View File

@@ -0,0 +1,86 @@
> Historical validation evidence from application commit `bd898e92d22f6c412e671908770f4d89c8ae12bc`. Commands retain their original paths; current tooling is documented in README.md.
# S12 implementation validation
## Delivered behavior
Scheduling starts through a short POST returning 202 and a run identifier.
The backend reserves and snapshots inputs before submitting background work;
completion applies a validated result or records a distinct unsuccessful outcome.
Per-show exclusion remains in the shared school service, with different shows
allowed to calculate concurrently. Status publication and subscription snapshots
share a lock so connecting cannot miss a transition between snapshot and subscription.
The solver publishes optimization phases and first feasible-solution discovery
through a callback. Intermediate assignments remain private. Final summaries
calculate the same attendance, spread and adjacency penalties as the solver.
SSE provides a current snapshot on connection and status changes, with separate
15-second heartbeats. The nginx proxy disables buffering. The frontend keeps one
application-wide connection, explicitly retries connection errors (including
permanent EventSource failures caused by proxy responses), and reconciles state
without event replay. Run identifiers deduplicate completion notifications.
## Validation
- Maven verify: 60 backend tests passed, plus 19 standards-checker regression tests.
- Backend line coverage: 1346/1384, or 97.25%, above the required 80%.
- Frontend: 30 unit tests, production build and ESLint.
- Playwright: three real REST/browser scenarios, including scheduling completion,
result summaries, a completion snackbar, reloading to recover the latest result
and suppression of old notifications after reload.
- HTTP SSE integration verifies initial snapshot, pushed completion and a new
connection recovering the completed run.
- Background tests cover duplicate exclusion, parallel shows, stale-result
rejection, preserved assignments, failure outcomes and retry after failure.
- Frontend tests cover missed completion after disconnect, reconnection, heartbeat
handling, deduplication, completion arriving before the POST response and a
locally started run completing before the first successful SSE connection.
- Real solver tests cover phase/discovery callbacks, distinct infeasible/no-solution
outcomes and objective-summary definitions including coach exemptions.
## Manual standards assessment
Scheduling states and phases use backend enums and frontend string unions while
preserving their JSON names. Initial SSE recovery notifies for locally tracked
running tasks while suppressing historical completions.
No waivers or weakened checks were introduced. The architecture tests pass.
New records contain immutable values; the SSE snapshot defensively copies its
list. The ten-component SchedulingRun record groups run identity, timestamps,
progress and outcome in one immutable snapshot, avoiding mutable task state in
API responses. Solver observers use the existing application-owned port and
framework-independent domain types; OR-Tools remains encapsulated in solver.
Retained review signals:
- SchedulingRuns fan-out (26): task orchestration uses JDK executor/collection
types, the scheduling port and immutable input/progress/result/status models.
Its injected dependencies remain two; splitting these short lifecycle methods
would distribute the shared publication and run-slot ordering.
- SchedulingEventsResource fan-out (16): SSE/Mutiny transport, JSON envelope and
service subscription types are confined to the REST adapter.
- OrToolsSchedulingEngine fan-out (21), solve cognitive complexity (11) and
length (41 code lines): the ordered three-stage loop retains deadline and
earlier-feasible-result fallback behavior while publishing phase/discovery.
requireSolution cyclomatic complexity (8) retains explicit mappings for stable
failure outcomes and their human-readable explanations.
- Integration/background test fan-out and the background lifecycle test's
34-line method reflect real HTTP/solver fixtures and lifecycle assertions.
Existing REST-test length signals remain below blocking limits after adapting
them to await background completion.
## Persistence follow-up in S16
The maintainer explicitly transferred durable scheduling status and
backend-restart recovery to S16 and approved completion of S12 with that scope
adjustment. S12 is IN_REVIEW in `in_review/S12_support-async-feedback-for-scheduling`;
implementation is ready for review and final acceptance is pending.
The application currently stores schools, saved assignments and the latest
scheduling status in memory. S16 now explicitly requires PostgreSQL storage of
accepted runs and their latest status, atomic durable result/status commits,
stable identifiers in recovered API/SSE snapshots and startup conversion of
previously running calculations to Interrupted without automatic resumption.
Restart/crash recovery tests belong to S16; the S12 validation above covers
navigation, browser reload and connection recovery within one backend lifetime.

View File

@@ -0,0 +1,182 @@
> Historical validation evidence from application commit `bd898e92d22f6c412e671908770f4d89c8ae12bc`. Commands retain their original paths; current tooling is documented in README.md.
# S16 implementation validation
## Delivered behavior
PostgreSQL owns normalized school, dancer, coach, group, membership, style, show,
daypart, appearance and ordered-assignment tables, plus the latest scheduling run.
Flyway V1 creates the schema, persistent identifier sequence, cross-school-safe
foreign keys and row constraints. School keys, runtime identifiers, relationship
identity, coach links, draft assignments and finalized state survive reload.
Application persistence uses JPA/Hibernate ORM with mapped entities in
`repository.entity` and `EntityManager` repositories. Relationships, element
collections, daypart order and orphan removal are managed by Hibernate; domain
objects and API responses remain framework independent. The hand-written JDBC
query/update layer and row readers have been removed.
The HTTP interceptor runs each school operation in a short repeatable-read JTA
transaction under the existing domain monitor. Reads convert managed entities into
detached domain snapshots. Hibernate's school `@Version` checks optimistic changes;
a change stamp marks child-only edits so the school revision advances exactly once.
Missing or stale caller revisions conflict before applying edits, and stale detached
JPA entities also fail. Successful graph merges flush before commit, and status
publication remains after durable commit. A single school-data endpoint gives the
editor a consistent data/revision snapshot. Open editors retain their original
revision across background refreshes; conflict responses preserve their input and
require reload before retry. Replacement imports retain the target school ID and
check the revision returned by preview. Existing JSON import/export semantics remain.
Domain-to-view projection now uses MapStruct 1.6.3 in the REST layer. The generated
CDI `DomainViewMapper` covers schools, dancers, groups, coaches, dayparts and shows.
A shared ID conversion projects relationships to ordered ID lists; validation results
remain an explicit argument and preferred-daypart defaults delegate to the existing
application rule. View record constructors retain their defensive copies. Entity to
domain graph construction remains explicit in the persistence adapter.
`unmappedTargetPolicy = ERROR` rejects missing target fields at compilation. A compiler
probe with the actual mapper and an added unmapped SchoolView component confirms this
failure, without modifying maintained sources. MapStruct's generated implementation
is marked `lombok.Generated`, preserving the existing generated-code scope of coverage
and architecture checks; handwritten mapper helpers remain covered and checked.
Flyway remains the schema authority; Hibernate validates rather than generates DDL.
V1 is unchanged. V2 preserves existing rows, adds the aggregate change stamp and a
JPA-managed identifier counter seeded above previously allocated IDs, and defers
date/type uniqueness until commit so Hibernate can reorder retained dayparts safely.
Identifier allocation takes a pessimistic lock on the counter row. Coach/dancer and
group/coach associations use Hibernate composite join mappings to share the owning
school key while letting Hibernate update the linked member column directly.
Run acceptance checks the school revision and persists the run before launch or
acknowledgement. Acceptance itself does not change scheduling inputs. Background
computation holds neither a database transaction nor the domain monitor. Progress
commits before publication. Successful assignment replacement, school revision and
terminal run status commit together; publication callbacks run only after commit.
Deferred constraint failures roll back both assignments and status without
publishing success. Database failure never falls back to acknowledged memory-only
writes. Disconnected status subscribers cannot turn a committed result into a
solver failure.
Startup recovery marks persisted Running runs Interrupted before serving status,
retains their IDs, progress and previous saved assignments, and creates no old run
guards. The frontend recognizes Interrupted and retains S12's reconnect/reload
notification behavior. Timestamps use PostgreSQL microsecond precision consistently
in live and recovered snapshots.
## Verification
- Maven clean verify: all 72 backend tests and 19 standards-checker regression tests
pass. The JPA integration run also verified Flyway V1 and V2 and Hibernate schema
validation against an empty database, as well as an upgrade of the populated V1
test database.
- Backend line coverage: 1763/1827 (96.50%), above the 80% gate.
- Frontend: 32 unit tests, production build and ESLint pass (unchanged by the
MapStruct-only backend change).
- Generated-mapper CDI tests cover ordered relationship IDs, an unlinked coach,
nested assignment order, defensive copies, explicit validation messages and the
configured/default preferred-daypart rule. The compile-time unmapped-field probe
passes with the expected compiler error.
- Playwright: the three existing real REST/browser scenarios pass with PostgreSQL;
a fourth scenario verifies two screens editing the same revision, conflict
handling with retained form input, and successful reload/retry.
- PostgreSQL tests cover simultaneous edits (one succeeds, one conflicts), missing
revisions, relational graph recovery, IDs and ordered assignments, finalized
state, deferred commit failure without success publication, failed replacement
import rollback, stale scheduling inputs and interrupted-run recovery. JPA-specific
tests verify stale detached entities, exactly one aggregate version increment for
child-only edits, and reordered dayparts retaining their assignments.
- `tooling/persistence/restart_test.py` runs the packaged production backend against
an isolated persistent PostgreSQL container. It passes graceful restart and
SIGKILL interruption checks, verifies a completed saved result after every
restart, checks stable recovered IDs through HTTP and SSE, starts a new run after
interruption, rejects mutations during a database outage, and verifies startup
failure for an unreachable database and a deliberately failing Flyway migration.
- CI helper tests: 17 pass. Release and actual deployment-shell behavior tests:
32 pass. Shell syntax and Java/frontend formatting checks pass.
The packaged-process checks deliberately stop/restart only the named disposable
test database. Production deployment was not performed. Database provisioning and
transition instructions are in `docs/persistent-storage.md`; export every school
before stopping the old in-memory release. Production Compose retains its database
volume outside application replacement. CI supplies a separate disposable browser
database and removes its anonymous volume during cleanup.
## Manual standards assessment
No waivers or weaker gates were added. Architecture tests pass. Persistence entities
and their embeddable keys belong to the repository layer, while the scheduling
records remain in `model.scheduling`. Mutable classes, no-argument construction,
setters and replaceable collections are deliberate JPA lifecycle requirements;
Hibernate installs managed collection wrappers and hydrates fields. Composite key
values are assigned before persistence and are not mutated afterward. None of these
entities or lazy collections escapes into the solver or the API. Existing immutable
snapshot records still defensively copy mutable collections.
Retained review signals in changed code:
- Database fan-out 27 and transaction cyclomatic complexity 8: JPA/JTA lifecycle,
rollback and heuristic failures, optimistic-conflict classification, and committed
publication are handled in one transaction owner. Its two injected dependencies
remain below the review signal.
- SchoolWriter fan-out 17: one adapter builds and merges the school graph, removes
deleted-show statuses, checks JPA revisions and flushes changes. PeopleMapping,
GroupMapping and ShowMapping separate domain conversion from ORM lifecycle.
- Entity fan-out reflects explicit relationship and collection annotations:
DayPartEntity 22, GroupEntity 24, RunEntity 17, SchoolEntity 18 and ShowEntity 23.
Each maps one existing table/aggregate boundary; splitting fields merely to lower
annotation-driven fan-out would obscure the relational mappings. Entity collections
are mutable only within the persistence adapter and Hibernate session.
- SchoolTransactions fan-out 19 and request cyclomatic complexity 9: four collaborators
cover the detached domain monitor, transaction owner, loader and writer. The branch
structure distinguishes reads, run acceptance and domain mutations and maps storage
failures separately from optimistic conflicts. SchoolChange's four components
keep the revision and operation classification together.
- SchedulingRuns fan-out 31: it coordinates immutable input/progress/run/result
records, the solver port, durable lifecycle operations and subscriber callbacks;
its three injected collaborators remain below the dependency review signal.
- SchoolManagementService fan-out 38, 30 public methods, beginScheduling
cyclomatic complexity 8 and the existing five-parameter updateShow are retained:
aggregate use cases and validations remain together. Load installs detached state
and resets transient input counters under the existing monitor.
- REST resource fan-out is 18–28 (DanceSchoolResource 25): resources combine HTTP
annotations, use cases, request/view contracts and the injected projection mapper.
The consistent data endpoint assembles views inside the transaction. DomainViewMapper
fan-out 25 represents six explicit source/target projections plus the MapStruct
annotations and two small shared helpers. DomainViewMapperTest fan-out 22 exercises
the generated CDI mapper's API edge cases. SchoolView's six components include the revision;
SchoolDataView's five components represent one editor snapshot. ImportPreview's
seventh component identifies the target revision for replacement.
- PersistenceTest fan-out 47, seven injected fixtures, 335 code lines and methods of
41/33/42 lines: these cross real ORM, graph and transaction boundaries, including
detached-entity conflicts, commit-time failure, failed import, child versioning and
reordered assignments. The fixtures remain below all blocking limits. Existing
changed REST/SSE/background fixture metrics retain their S12/S7 rationale.
One active backend remains the supported deployment model. Global execution
capacity, distributed workers, database backup/restore and recovery after database
volume loss remain outside S16. S17 owns backup/restore.
## Review follow-up: database recovery during calculation
Terminal scheduling outcomes whose transaction fails remain pending in their worker.
The worker retries storage once per second without holding the school monitor between
attempts, retaining its run guard until the terminal status commits. Publication still
happens only after commit. Shutdown interrupts the wait; startup recovery remains
responsible for persisted Running statuses after a process restart. If the show was
removed during the outage, the pending outcome is discarded rather than recreating
its status. The finish method's cognitive complexity 12 and cyclomatic complexity 8 distinguish
retryable storage failures, removed shows and shutdown; these lifecycle decisions
stay in the run owner. SchedulingRuns fan-out is now 34 and its test fixture fan-out
35: the added storage exception, interruption handling and outage fixture belong to
this existing persistence lifecycle boundary.
The regression test simulates unavailable storage during result persistence, verifies
that no terminal status is published prematurely and duplicate starts remain rejected,
then restores storage without restarting the backend and checks the stable run ID,
persisted failure status and released guard. Public transaction/callback documentation
now specifies transaction ownership, callback timing and exception behavior.
Follow-up verification: clean Maven verify against PostgreSQL passes all 73 backend
tests and 19 standards-checker tests. Standards and the coverage gate pass;
backend line coverage is 1769/1841 (96.09%).

View File

@@ -0,0 +1,54 @@
DESIGN agiledancers-be/src/main/java/nl/agilecc/agiledancers/model/scheduling/GroupRequirement.java:3 recordComponents=2 (manual design review)
DESIGN agiledancers-be/src/main/java/nl/agilecc/agiledancers/model/scheduling/SchedulingInput.java:5 recordComponents=4 (manual design review)
DESIGN agiledancers-be/src/main/java/nl/agilecc/agiledancers/model/scheduling/SchedulingResult.java:7 recordComponents=2 (manual design review)
DESIGN agiledancers-be/src/main/java/nl/agilecc/agiledancers/rest/apimodel/DancerRequest.java:8 recordComponents=2 (manual design review)
DESIGN agiledancers-be/src/main/java/nl/agilecc/agiledancers/rest/apimodel/DancerView.java:6 recordComponents=3 (manual design review)
DESIGN agiledancers-be/src/main/java/nl/agilecc/agiledancers/rest/apimodel/DayPartRequest.java:7 recordComponents=2 (manual design review)
DESIGN agiledancers-be/src/main/java/nl/agilecc/agiledancers/rest/apimodel/DayPartView.java:9 recordComponents=3 (manual design review)
DESIGN agiledancers-be/src/main/java/nl/agilecc/agiledancers/rest/apimodel/ErrorView.java:6 recordComponents=1 (manual design review)
DESIGN agiledancers-be/src/main/java/nl/agilecc/agiledancers/rest/apimodel/GroupRequest.java:12 recordComponents=5 (manual design review)
DESIGN agiledancers-be/src/main/java/nl/agilecc/agiledancers/rest/apimodel/GroupView.java:13 recordComponents=7 (manual design review)
DESIGN agiledancers-be/src/main/java/nl/agilecc/agiledancers/rest/apimodel/SchedulingView.java:3 recordComponents=2 (manual design review)
DESIGN agiledancers-be/src/main/java/nl/agilecc/agiledancers/rest/apimodel/SchoolRequest.java:5 recordComponents=1 (manual design review)
DESIGN agiledancers-be/src/main/java/nl/agilecc/agiledancers/rest/apimodel/SchoolView.java:11 recordComponents=5 (manual design review)
DESIGN agiledancers-be/src/main/java/nl/agilecc/agiledancers/rest/apimodel/ShowRequest.java:13 recordComponents=3 (manual design review)
DESIGN agiledancers-be/src/main/java/nl/agilecc/agiledancers/rest/apimodel/ShowView.java:13 recordComponents=4 (manual design review)
DESIGN agiledancers-be/src/main/java/nl/agilecc/agiledancers/service/model/Group.java:9 recordComponents=8 (manual design review)
DESIGN agiledancers-be/src/main/java/nl/agilecc/agiledancers/service/model/GroupDetails.java:9 recordComponents=5 (manual design review)
DESIGN agiledancers-be/src/main/java/nl/agilecc/agiledancers/service/model/ImportPreview.java:3 recordComponents=6 (manual design review)
DESIGN agiledancers-be/src/main/java/nl/agilecc/agiledancers/service/model/Part.java:9 recordComponents=3 (manual design review)
DESIGN agiledancers-be/src/main/java/nl/agilecc/agiledancers/service/model/Performance.java:10 recordComponents=4 (manual design review)
DESIGN agiledancers-be/src/main/java/nl/agilecc/agiledancers/service/model/Person.java:5 recordComponents=3 (manual design review)
DESIGN agiledancers-be/src/main/java/nl/agilecc/agiledancers/service/model/SchoolSnapshot.java:27 recordComponents=7 (manual design review)
DESIGN agiledancers-be/src/main/java/nl/agilecc/agiledancers/service/model/Trainer.java:3 recordComponents=2 (manual design review)
REVIEW agiledancers-be/src/main/java/nl/agilecc/agiledancers/model/DanceGroup.java:18 fanOut=16.0
REVIEW agiledancers-be/src/main/java/nl/agilecc/agiledancers/model/DanceSchool.java:16 fanOut=16.0
REVIEW agiledancers-be/src/main/java/nl/agilecc/agiledancers/rest/DanceGroupResource.java:28 fanOut=21.0
REVIEW agiledancers-be/src/main/java/nl/agilecc/agiledancers/rest/DanceSchoolResource.java:27 fanOut=20.0
REVIEW agiledancers-be/src/main/java/nl/agilecc/agiledancers/rest/DancerResource.java:27 fanOut=20.0
REVIEW agiledancers-be/src/main/java/nl/agilecc/agiledancers/rest/SchoolSnapshotResource.java:26 fanOut=25.0
REVIEW agiledancers-be/src/main/java/nl/agilecc/agiledancers/rest/ShowResource.java:32 fanOut=25.0
REVIEW agiledancers-be/src/main/java/nl/agilecc/agiledancers/rest/apimodel/GroupView.java:21 parameters=7.0
REVIEW agiledancers-be/src/main/java/nl/agilecc/agiledancers/service/SchoolManagementService.java:102 cyclomatic=8.0
REVIEW agiledancers-be/src/main/java/nl/agilecc/agiledancers/service/SchoolManagementService.java:282 executableLines=33.0
REVIEW agiledancers-be/src/main/java/nl/agilecc/agiledancers/service/SchoolManagementService.java:282 parameters=5.0
REVIEW agiledancers-be/src/main/java/nl/agilecc/agiledancers/service/SchoolManagementService.java:35 fanOut=35.0
REVIEW agiledancers-be/src/main/java/nl/agilecc/agiledancers/service/SchoolManagementService.java:35 publicMethods=28.0
REVIEW agiledancers-be/src/main/java/nl/agilecc/agiledancers/service/model/SchoolSnapshot.java:136 executableLines=37.0
REVIEW agiledancers-be/src/main/java/nl/agilecc/agiledancers/service/model/SchoolSnapshot.java:174 executableLines=35.0
REVIEW agiledancers-be/src/main/java/nl/agilecc/agiledancers/service/model/SchoolSnapshot.java:27 fanOut=29.0
REVIEW agiledancers-be/src/main/java/nl/agilecc/agiledancers/service/model/SchoolSnapshot.java:35 parameters=7.0
REVIEW agiledancers-be/src/main/java/nl/agilecc/agiledancers/service/model/SchoolSnapshot.java:42 executableLines=41.0
REVIEW agiledancers-be/src/main/java/nl/agilecc/agiledancers/solver/OrToolsSchedulingEngine.java:20 fanOut=17.0
REVIEW agiledancers-be/src/test/java/nl/agilecc/agiledancers/SchedulingTest.java:29 fanOut=22.0
REVIEW agiledancers-be/src/test/java/nl/agilecc/agiledancers/SchoolManagementResourceTest.java:123 executableLines=44.0
REVIEW agiledancers-be/src/test/java/nl/agilecc/agiledancers/SchoolManagementResourceTest.java:168 executableLines=38.0
REVIEW agiledancers-be/src/test/java/nl/agilecc/agiledancers/SchoolManagementResourceTest.java:26 executableLines=39.0
REVIEW agiledancers-be/src/test/java/nl/agilecc/agiledancers/SchoolSnapshotResourceTest.java:16 executableLines=40.0
REVIEW agiledancers-be/src/test/java/nl/agilecc/agiledancers/SchoolSnapshotTest.java:30 fanOut=19.0
REVIEW agiledancers-be/src/test/java/nl/agilecc/agiledancers/SchoolSnapshotTest.java:56 executableLines=32.0
REVIEW agiledancers-be/src/test/java/nl/agilecc/agiledancers/SnapshotCollectionsTest.java:26 fanOut=22.0
REVIEW agiledancers-be/src/test/java/nl/agilecc/agiledancers/service/SchedulingServiceTest.java:28 fanOut=28.0
REVIEW agiledancers-be/src/test/java/nl/agilecc/agiledancers/service/SchedulingServiceTest.java:29 executableLines=32.0
REVIEW agiledancers-be/src/test/java/nl/agilecc/agiledancers/service/SchedulingServiceTest.java:62 executableLines=38.0
WAIVER agiledancers-be/src/main/java/nl/agilecc/agiledancers/service/model/Group.java:19 parameters=8.0 Maintainer approved in the S7 implementation conversation: preserve the eight-component version-2 JSON shape while defensively copying styles and dancerIds.

View File

@@ -0,0 +1,127 @@
> Historical validation evidence from application commit `bd898e92d22f6c412e671908770f4d89c8ae12bc`. Commands retain their original paths; current tooling is documented in README.md.
# S7 implementation and validation evidence
Status: IN_REVIEW — implementation complete; awaiting project review.
Date: 2026-10-30. Environment: Ubuntu amd64, OpenJDK 25.0.4.1, Maven 3.9.16.
## Delivered changes
Enforcement/configuration: root coding standards and agent discovery instructions;
project review companion (upstream skills unchanged); individually selected
Checkstyle 12.3.1 checks; PMD/CPD 7.28.0 with targeted measurements and regression
fixtures; JaCoCo 0.8.14 with exact line-count gates; verify integration; Docker
build inputs; CI instrumentation, merge and diagnostic retention. No broad
standards/coverage exclusions or unrelated rule bundles were introduced.
Migration: explicit imports and visibility, required finality and explicit types;
an explicit collaborator constructor for scheduling tests while preserving CDI field injection and the public no-argument constructor; smaller snapshot-restoration,
import-rebuilding, solver and validation methods; smaller HTTP test helpers;
null-tolerant defensive collection copies for records, including both levels of
solver assignments. Existing entity classes retain their mutation, Lombok and
framework contracts. API paths, payloads, snapshot version and persistence behavior
are unchanged. Enforcement and migration can be reviewed separately by path.
## Scope, tools and measurements
58 handwritten production files and 9 handwritten test files are checked.
Generated target output, frontend code and Java helpers outside the backend are
outside that standards scope. All handwritten production packages participate in
coverage, including DTOs and configuration. JaCoCo's generated-member filtering is
used; no handwritten class/package exclusions are configured.
See CODING_STANDARDS.md for complete targets, strict thresholds, algorithm options,
manual rules, scope and standalone commands. The full current metrics report is
`agiledancers-be/target/standards/report.txt`. Production CPD currently reports
**0%** duplicated code lines at its 100-token minimum. Test duplication is not gated.
The selected PMD finality rules complement custom checks. PMD cyclomatic and
cognitive visitors are scoped explicitly: lambdas contribute, nested/local type
methods are independent, and no aggregate class complexity gate is introduced.
Resolved collaborator identity includes qualifier values/defaults and inherited
generic type substitution. Exact metric waivers are supported and regression tested;
`tooling/standards/waivers.tsv` records the sole approved waiver: the exact
eight-parameter Group constructor needed to preserve its version-2 JSON shape.
## Reproducible validation
Set JAVA_HOME to JDK 25 and run from the repository root.
| Command/check | Result |
| --- | --- |
| `mvn -Dformat.mode=check clean verify` | Passed: 38 backend tests, 19 checker tests, standards checks and the exact backend coverage gate. |
| `mvn -pl agiledancers-be package -DskipTests` | Passed; Quarkus packaged app successfully produced and subsequently exercised by Playwright. |
| `mvn -f tooling/standards/pom.xml test exec:java` | 19 checker tests passed; no unwaived blocking violations. |
| `java tooling/coverage/Coverage.java agiledancers-be/target/site/jacoco/jacoco.xml` | Clean backend-only line gate passed: 791 covered / 818 total = 96.69926650366749%. |
| `PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH=/opt/google/chrome/chrome npm run e2e` in frontend | Both browser tests passed against the packaged instrumented backend. |
| Pinned CLI `dump --address 127.0.0.1 --destfile agiledancers-be/target/playwright.exec` | Successfully collected execution data from the agent's TCP server. |
| `mvn -pl agiledancers-be jacoco:merge@combined jacoco:report@combined-report exec:exec@combined-coverage` | Passed with matching clean-build application classes: combined 791/818 lines, 96.69926650366749%. |
| `java ci/Ci.java test` | 17 CI orchestration tests passed. |
| `git diff --check` | Passed. |
Both local and combined branch reports contain 195 covered / 257 total branches
(75.87548638132296%); branches have no blocking percentage. Browser coverage is
successfully collected and merged, but does not add uncovered lines in this run.
Local and combined HTML/XML/CSV reports are under `agiledancers-be/target/site`.
Execution data is in `target/jacoco.exec`, `target/playwright.exec` and
`target/jacoco-combined.exec` within the backend module. CI copies these reports,
execution data and checker results into its retained diagnostics. Local validation
exercised collection and merge; a remote Gitea publication run was not performed.
The checker fixtures cover strict complexity, length, parameter, nesting,
inheritance and dependency boundaries; implicit/compact record constructors;
lambda/nested-type scope; comments/brace lines; distinct type fan-out; nontrivial
accessors; qualifiers, repeated and inherited injection; exact waivers; parser
failure diagnostics; report-only behavior; CPD occurrence/overlap accounting and
test exclusion; and the unrounded 80% line gate, including a near miss.
## Retained review signals
`S7-review-signals.txt` records the current individual REVIEW and DESIGN entries.
The following assessment covers every retained review-signal group. The approved
constructor waiver is documented separately below.
| Signal/location | Assessment and reason retained |
| --- | --- |
| DanceGroup and DanceSchool fan-out 16 | Domain collection/entity references and explicitly used Lombok annotations are intrinsic to these mutable aggregates. Converting them to records would break their mutation/inheritance contracts. |
| Five REST resources, fan-out 20–25 | HTTP annotations, response/request types and service/domain mapping account for the references. These are thin adapters; splitting them to reduce annotation counts would obscure endpoint ownership. |
| GroupView and SchoolSnapshot compact constructors, 7 parameters | Their components preserve existing JSON contracts. Constructors only protect collections and are within the allowed constructor limit. |
| SchoolManagementService fan-out 35, public methods 28 | One shared synchronization boundary owns in-memory aggregate writes and scheduling revisions. Splitting state/locks needs its own concurrency design; the class passes blocking length/dependency limits. |
| validateAssignments cyclomatic 8 | Independent input/result guards and required-appearance validation are explicit and tested; per-part validation has already been extracted. It remains below the blocking limit. |
| updateShow, 33 lines and 5 parameters | Retains assignments by matching daypart keys before replacing the aggregate. Keeping the transaction visible and preserving its existing signature is preferable to artificial wrappers; both blocking limits pass. |
| SchoolSnapshot fan-out 29; of 41 lines, restoreGroups 37, restoreShows 35 | Each method performs one graph conversion phase. Explicit type/reference checks protect imported data and preserve assignment identity. Refactoring has removed the over-limit monolithic restore method. |
| Solver fan-out 17 | OR-Tools types are confined to this adapter and its dedicated helpers. Further indirection would spread solver details without improving the domain boundary. |
| SchedulingTest, SchoolSnapshotTest, SnapshotCollectionsTest and SchedulingServiceTest fan-out | These behavior tests intentionally exercise multiple collaborating models, services, ports, exceptions and assertions. Production architecture remains covered separately by ArchUnit. |
| HTTP, snapshot and scheduling test methods at 32–44 lines | Arrange/action/assert and try/finally cleanup remain together. Repeated setup was extracted where methods exceeded 50 physical code lines; retained methods pass all blocking limits. |
| All DESIGN record-component entries | Request/view/snapshot/domain records model existing named contracts; their sizes are not automatically gated. Mutable components are copied, including both Group lists under its approved constructor waiver. Framework-backed mutable entities remain classes. |
## Approved compatibility decisions
The maintainer approved both proposals in the S7 implementation conversation:
1. `GroupDetails` groups category, type, age bounds and styles. The Java signatures
of `DanceGroupService.add`, `SchoolManagementService.createGroup` and
`updateGroup` now take 3, 2 and 3 parameters respectively. All callers were
migrated. REST endpoints, JSON payloads and snapshot version remain unchanged.
The record copies its styles, and service construction takes a mutable copy
for the domain group; regression coverage verifies later style edits still work.
2. The explicit eight-component `service.model.Group` constructor defensively
copies styles and dancer IDs while preserving null values for existing import
validation. Its sole waiver matches the fully resolved constructor signature,
metric and exact retained value 8. The agreement and reason are recorded in
`tooling/standards/waivers.tsv` and the result remains visible as `WAIVER`.
There are no parameter waivers for the three service methods, blanket suppressions
or weakened thresholds. The completed specification resides in `specs/in_review`.
## Review fixes
The review fixes enforce finality for assign-once pattern bindings, including
`instanceof`, switch and record-deconstruction bindings, while allowing reassigned
bindings and inferred record-pattern types. Trivial-accessor detection now uses
AST statements and resolved field/parameter references, so comments do not change
public-method counts. Accessors with calls, extra statements or compound
assignments still count. Two regression tests cover these cases.
After these fixes, JDK 25 `mvn -B -ntp -Dformat.mode=check verify` passed with
38 backend tests, 19 checker tests and backend line coverage of 791/818 (96.70%).

View File

@@ -0,0 +1,98 @@
> Historical validation evidence from application commit `bd898e92d22f6c412e671908770f4d89c8ae12bc`. Commands retain their original paths; current tooling is documented in README.md.
# S8 implementation evidence
Measured on 2026-10-30 on Linux x86_64 (kernel 7.0.0-38-generic), AMD Ryzen 7
7730U, 16 logical CPUs; Ubuntu OpenJDK 25.0.4.1, Maven 3.9.16. These are local
wall-clock measurements, not universal performance guarantees.
## Integration and scope
- exec-maven-plugin 3.6.3; OpenRewrite core 8.63.4; Palantir Java Format 2.101.0.
- Custom `Format.PalantirRecipe` processes OpenRewrite PlainText source files
using Palantir's `formatSourceAndFixImports`, Palantir style, `formatJavadoc(false)`.
No Java type attribution, OpenRewrite Java parser or AutoFormat is involved.
- 73 maintained Java files: 65 backend production/test files, 7 CI/runner helpers,
and the formatter helper. Recursive discovery excludes generated build output.
- Root validate executes before compilation; compile/test/verify/install all reach
validate. CI explicitly passes check mode to clean verify. Standalone commands
run only the root exec execution and do not compile the backend.
- Bootstrap was first executed with neither Palantir nor OpenRewrite in the local
Maven repository. The helper is source-launched, with dependencies supplied by
Maven's plugin classpath. There is no project recipe artifact to preinstall.
The isolated regression fixture also has no compiled adapter or backend module.
## Correctness
- Full `mvn -B -ntp clean verify` passed after formatting: 33 backend tests,
zero failures/errors/skips. Both benchmark clean verifications also pass.
- `java ci/Ci.java test`: 17 passed, including assertion of the exact check-only
Maven invocation and that Maven failure removes the success marker and prevents
image build/publication.
- `python3 tooling/format/test.py` checks an isolated source-launcher checkout:
read-only check failure with path and apply command; native unused-import
removal; UTF-8 non-ASCII preservation; check/apply agreement; second uncached
check with no differences; malformed Java fails with its path and leaves the
source bytes unchanged; a newly introduced file cannot evade the content cache.
- All current Java files have been processed by the real engine on JDK 25,
including records, switch expressions/multiple labels, pattern instanceof,
lambdas and source-launcher CI classes. Tests compile/run the resulting sources.
This demonstrates the syntax used here, not every possible Java 25 construct.
- Palantir uses javac internals (explicit JVM exports are in the root POM) and its
modern AST visitor. Recheck formatter compatibility when upgrading the JDK.
Compact source files / instance main methods are a known upstream limitation
([upstream issue](https://github.com/palantir/palantir-java-format/issues/1602));
they are not used here. Unsupported future syntax fails, rather than being
silently excluded. Extra Markdown/Javadoc formatting is disabled.
- The initial Java rewrite is committed separately from integration changes;
its only transformations are the formatter's native output and import handling.
## Performance
`python3 tooling/format/benchmark.py` runs sequentially, with normal dependencies
and OS filesystem caches warm. Each configuration receives a compile warmup.
The baseline temporarily removes the entire exec plugin declaration from the
root POM, then restores its original bytes before the formatting build. Therefore
these comparisons include plugin loading, dependency resolution, JVM launch,
source-launcher compilation, hashing, cache IO and recipe execution. They do not
compare only the inner formatter function or a skipped plugin against itself.
The successful-content cache is warm for unchanged builds; it is part of the
integration. Changed/new files are processed by Palantir. Clean builds remove the
cache and process every maintained Java file. Each run's stdout and elapsed time
are saved under `target/`; the benchmark restores the root POM and changed helper.
| Repeated compile | Baseline (s) | Integration (s) | Added overhead (s) |
| --- | ---: | ---: | ---: |
| 1 | 4.887 | 6.414 | 1.527 |
| 2 | 4.821 | 5.964 | 1.143 |
| 3 | 4.559 | 6.024 | 1.465 |
Maximum observed added overhead: **1.527 seconds**, below the agreed three-second
limit. Baseline compile warmup: 5.307 s; integration warmup: 7.604 s.
The changed-file case appends a newline to `ci/runner/WaitForDocker.java`, then
runs `mvn -B -ntp compile`: **5.506 s**, successful; Palantir processes that
changed file. The script restores its original bytes afterward.
Clean baseline `mvn -B -ntp clean verify`: **24.797 s**. Clean integration
`mvn -B -ntp -Dformat.mode=check clean verify`: **27.747 s**, all 73 files
processed, no differences, all tests pass. The three-second criterion applies
to repeated unchanged builds, not the clean-build comparison.
### First-use downloads (separate measurement)
A disposable root POM with the same pinned plugin/dependencies and an empty
`-Dmaven.repo.local` replaces only the Java executable with `/usr/bin/true`.
Thus dependency resolution runs without compiling the launcher or executing the
formatter/application. Command:
`mvn -N -B -ntp -Dmaven.repo.local=<empty-temp-repository> org.codehaus.mojo:exec-maven-plugin:3.6.3:exec@format`.
Cold resolution took **9.041 s**; the same command with that repository populated
took **1.826 s**. The **7.215 s** cold-versus-warm difference represents first-use
network/repository population overhead in this environment, separately from the
warm-cache build measurements above. Cold timing also includes root POM/BOM and
plugin bootstrap resolution; it is not reported as pure formatter execution.
Reproduce with `python3 tooling/format/benchmark-downloads.py` (Linux, network
access). The initial real source-launcher bootstrap/check also successfully
processed all files; its expected failure listed formatting differences, rather
than a missing project recipe or parser/bootstrap error.