S19: consume versioned engineering resources and move landscape documentation
All checks were successful
Build, test and publish / verify (push) Successful in 8m54s
All checks were successful
Build, test and publish / verify (push) Successful in 8m54s
This commit is contained in:
3
docs/S19-classification.md
Normal file
3
docs/S19-classification.md
Normal 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
36
docs/S19-validation.md
Normal 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.
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
```
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
86
docs/validation/S12-validation.md
Normal file
86
docs/validation/S12-validation.md
Normal 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.
|
||||
182
docs/validation/S16-validation.md
Normal file
182
docs/validation/S16-validation.md
Normal 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%).
|
||||
54
docs/validation/S7-review-signals.txt
Normal file
54
docs/validation/S7-review-signals.txt
Normal 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.
|
||||
127
docs/validation/S7-validation.md
Normal file
127
docs/validation/S7-validation.md
Normal 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%).
|
||||
98
docs/validation/S8-formatting-evidence.md
Normal file
98
docs/validation/S8-formatting-evidence.md
Normal 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.
|
||||
Reference in New Issue
Block a user