S19: establish landscape repository
This commit is contained in:
10
specs/README.md
Normal file
10
specs/README.md
Normal file
@@ -0,0 +1,10 @@
|
||||
# Specifications
|
||||
|
||||
Store feature specifications, requirements and agreed design decisions here.
|
||||
Use descriptive Markdown filenames, prefixed with a unique S# reference, for example `S1_school-json-import-export.md`.
|
||||
Each spec-file will get a Status with either the values: NEW, REFINED, IN PROGRESS, IN REVIEW, IMPLEMENTED, REJECTED.
|
||||
Each spec-file that is refined with the grill-me skill, or manually, will be moved to the refined-folder, and its status-field will be set to REFINED.
|
||||
When a spec-file gets implemented, at first, the spec-file will be moved to the in_progress-folder, and its status-field will be set to IN_PROGRESS.
|
||||
When a spec-file is fully implemented, the spec-file will be moved to the in_review-folder, and its status-field will be set to IN_REVIEW.
|
||||
When a spec-file is reviewed, the spec-file will be moved to the implemented-folder, and its status-field will be set to IMPLEMENTED.
|
||||
When a spec-file is rejected, the spec-file will be moved to the rejected-folder, and its status-field will be set to REJECTED.
|
||||
7
specs/S10_allow-group-exclusion-for-show
Normal file
7
specs/S10_allow-group-exclusion-for-show
Normal file
@@ -0,0 +1,7 @@
|
||||
As DanceSchool Maintainer
|
||||
I want the ability to exclude certain groups for a specific show
|
||||
so that I can diversify in the groups and shows that we offer.
|
||||
|
||||
State: NEW
|
||||
|
||||
Affected repositories: `agiledancers`.
|
||||
3
specs/S11_add-season-context-to-groups-and-shows
Normal file
3
specs/S11_add-season-context-to-groups-and-shows
Normal file
@@ -0,0 +1,3 @@
|
||||
|
||||
|
||||
Affected repositories: `agiledancers`.
|
||||
@@ -0,0 +1,3 @@
|
||||
|
||||
|
||||
Affected repositories: `agiledancers`.
|
||||
3
specs/S14_add-sonar
Normal file
3
specs/S14_add-sonar
Normal file
@@ -0,0 +1,3 @@
|
||||
|
||||
|
||||
Affected repositories: `agiledancers`.
|
||||
5
specs/S15_add-DoD
Normal file
5
specs/S15_add-DoD
Normal file
@@ -0,0 +1,5 @@
|
||||
- tested
|
||||
- changelog
|
||||
- documented
|
||||
|
||||
Affected repositories: `agiledancers`.
|
||||
3
specs/S17_database-backup-and-restore
Normal file
3
specs/S17_database-backup-and-restore
Normal file
@@ -0,0 +1,3 @@
|
||||
|
||||
|
||||
Affected repositories: `agiledancers`.
|
||||
3
specs/S3_define-coding-standards-to-fe
Normal file
3
specs/S3_define-coding-standards-to-fe
Normal file
@@ -0,0 +1,3 @@
|
||||
Create a file (or append to it) CODING_STANDARDS.md and have the coding standards in there, for the review skill.
|
||||
|
||||
Affected repositories: `agiledancers`.
|
||||
58
specs/School-JSON-format.md
Normal file
58
specs/School-JSON-format.md
Normal file
@@ -0,0 +1,58 @@
|
||||
# School JSON format, version 3
|
||||
|
||||
Export: `GET /api/dance-schools/{id}/export` downloads readable JSON.
|
||||
Preview: `POST /api/dance-schools/import/preview` accepts the file itself as
|
||||
`application/json`, validates without writing, and returns `name`, `dancers`,
|
||||
`groups`, `shows`, `existingId` and `existingName`.
|
||||
Commit: `POST /api/dance-schools/import` accepts the same file. For replacement,
|
||||
provide `?replaceId=<existingId>` as explicit confirmation. A mismatch is rejected;
|
||||
refresh the preview if another import added or removed the school meanwhile.
|
||||
There is no merge endpoint.
|
||||
|
||||
```json
|
||||
{
|
||||
"formatVersion": 3,
|
||||
"key": "1b8fe22c-5ac3-4ab9-a2c8-d1d28d2becee",
|
||||
"name": "Studio",
|
||||
"dancers": [{ "id": "d1", "name": "Sam", "birthDate": "2010-05-12" }],
|
||||
"coaches": [{ "id": "c1", "name": "Alex", "dancerId": "d1" }],
|
||||
"groups": [{
|
||||
"id": "g1", "category": "Hiphop", "type": "REGULAR",
|
||||
"startAge": 12, "endAge": 18, "styles": ["HIPHOP"],
|
||||
"dancerIds": ["d1"], "coachId": "c1"
|
||||
}],
|
||||
"shows": [{
|
||||
"id": "s1", "name": "Summer show", "preferredDayParts": 1, "finalized": false,
|
||||
"dayParts": [{ "date": "2027-06-12", "type": "MORNING", "groupIds": ["g1"] }]
|
||||
}]
|
||||
}
|
||||
```
|
||||
|
||||
`key` is a persistent UUID independent of the server's numeric school ID. IDs
|
||||
inside each collection are nonblank strings, unique within that collection, and
|
||||
local to this file. They can change on export. References must resolve within the
|
||||
file. A dancer or coach can be referenced by multiple groups. A group can appear
|
||||
in multiple day parts. A date/type combination can occur once per show, with at most six dayparts.
|
||||
|
||||
The optional `coachId` and coach `dancerId` references may be absent or null.
|
||||
`preferredDayParts` defaults to two (one for a single daypart); `finalized`
|
||||
defaults to false. Legacy version 2 files remain supported; version 1 is rejected.
|
||||
Legacy `appearances` counts may be present but do not govern S18 scheduling.
|
||||
Every imported schedule becomes a draft, even when exported as final.
|
||||
`preferredDayParts` must be an integer from one to six; a retained value exceeding
|
||||
the daypart count must be corrected before scheduling or finalization. Collections
|
||||
may be empty. Names/category must be nonblank. Dates use ISO `yyyy-MM-dd`;
|
||||
birth dates cannot be in the future. Ages are nonnegative integers with
|
||||
`startAge <= endAge`. Enum values use the same uppercase names as the management
|
||||
API. Day-part types are `MORNING`, `AFTERNOON`, `EVENING`.
|
||||
Unknown fields, duplicate JSON properties, duplicate IDs or membership references, invalid
|
||||
values and unsupported versions are rejected. Validation is repeated on commit.
|
||||
The entire school is prepared before publishing it under the shared service lock.
|
||||
Replacing retains the numeric school ID for existing browser links; imported
|
||||
child IDs are reassigned to avoid collisions with other schools.
|
||||
|
||||
Group types: `SHOW_CASE`, `PRE_EDUCATION`, `SELECTION`, `REGULAR`, `PRE_SCHOOLER`.
|
||||
Styles: `HIPHOP`, `JAZZ`, `MODERN`, `STREETDANCE`, `CLASSIC`, `BREAKDANCE`.
|
||||
|
||||
|
||||
Affected repositories: `agiledancers`.
|
||||
147
specs/implemented/S12_support-async-feedback-for-scheduling
Normal file
147
specs/implemented/S12_support-async-feedback-for-scheduling
Normal file
@@ -0,0 +1,147 @@
|
||||
# S12 — Asynchronous feedback for scheduling
|
||||
|
||||
Status: IMPLEMENTED
|
||||
|
||||
Agreed after the grill-me interview; shared understanding confirmed.
|
||||
|
||||
## User story
|
||||
|
||||
As a dance-school maintainer, I want feedback after starting Schedule Groups,
|
||||
so that I can see whether the backend is still calculating, when it finishes
|
||||
and what the outcome is, including when I leave and return to the show page.
|
||||
|
||||
## Background execution and concurrency
|
||||
|
||||
- Start scheduling in the backend without keeping the initiating HTTP request
|
||||
open until the calculation finishes. Navigation, page reloads and disconnected
|
||||
clients must not stop the calculation.
|
||||
- The backend owns the current scheduling status for each show. All open
|
||||
screens see the same status, including screens that did not start the run.
|
||||
- Allow at most one active calculation per show. Disable Schedule Groups while
|
||||
it is running and reject duplicate starts in the backend as well.
|
||||
- Different shows may calculate concurrently. A global capacity limit and a
|
||||
waiting queue are outside S12.
|
||||
- Retain the existing 30-minute solver limit and scheduling rules.
|
||||
|
||||
## Progress and outcomes
|
||||
|
||||
- While running, show elapsed time, the current optimization phase (attendance,
|
||||
spread or variety), and whether a valid solution has been found.
|
||||
- Report a valid solution as soon as the solver discovers one, including during
|
||||
a phase. Extend solver progress reporting rather than waiting for the phase
|
||||
to finish. Do not apply intermediate solutions.
|
||||
- Do not present a completion percentage or estimated finish time: the phases
|
||||
do not represent proportional parts of the calculation time.
|
||||
- Keep the latest status and outcome per show until a new calculation starts.
|
||||
Show the finish time and distinguish an optimal solution from a valid solution
|
||||
whose optimality was not proven within the time limit.
|
||||
- For a successful result, show a concise summary with concrete results for
|
||||
attendance, spread and variety, using understandable labels.
|
||||
- Clearly distinguish invalid input, infeasibility, solver failure, time limit
|
||||
without a valid solution and rejection because inputs changed. Explain why
|
||||
no result was applied and that existing assignments were preserved.
|
||||
Backend-restart interruption recovery belongs to S16.
|
||||
|
||||
## Applying results
|
||||
|
||||
- Retain the confirmation before starting that explains replacement of existing
|
||||
assignments. A successful completed calculation automatically replaces them;
|
||||
no preview/apply step is introduced.
|
||||
- A valid solution may be applied when the time limit expires even if optimality
|
||||
has not been proven.
|
||||
- Preserve the existing scheduling input revision check. A result based on
|
||||
outdated inputs must not replace the current assignments.
|
||||
- Failed, infeasible, interrupted, stale and no-solution calculations preserve
|
||||
existing assignments.
|
||||
- Report success only after the resulting assignments have been saved. Keep
|
||||
status and saved results consistent.
|
||||
|
||||
## Server-sent events and connection recovery
|
||||
|
||||
- Use server-sent events (SSE) for backend-to-frontend status updates.
|
||||
- On initial connection and reconnection, provide the current backend status.
|
||||
Correctness must not depend on receiving every previous event.
|
||||
- Maintain updates across navigation within the application so completion
|
||||
notifications can appear outside the show page.
|
||||
- If the connection is lost, indicate that displayed status may be outdated
|
||||
while the backend calculation continues. Reconnect and reconcile with the
|
||||
current status when connectivity returns.
|
||||
- Configure the application's proxy for streaming so updates reach the client
|
||||
promptly rather than being buffered until completion.
|
||||
|
||||
## Completion notifications
|
||||
|
||||
- Show an application-wide snackbar when a calculation completes or fails,
|
||||
including when the user has navigated to another application page.
|
||||
- Include the show name, a short outcome and a View show action.
|
||||
- Phase changes update progress without generating snackbars.
|
||||
- After temporary connection loss, show a missed completion notification once
|
||||
when the connection recovers. Reconnection must not repeatedly notify for
|
||||
the same completion.
|
||||
- Do not replay old snackbars on page reload or reopening the application;
|
||||
show the retained status on the show page instead.
|
||||
- Email, browser notifications and notifications outside the application are
|
||||
outside S12.
|
||||
|
||||
## Persistence and backend restarts
|
||||
|
||||
The maintainer explicitly transferred durable scheduling status and recovery
|
||||
following backend restarts to [S16](../in_review/S16_store-state-in-persistent-storage)
|
||||
when completing S12. The latest status and outcome in S12 survive navigation,
|
||||
page reloads and SSE reconnection while the same backend process remains active.
|
||||
Schools, assignments and scheduling status currently remain in memory.
|
||||
|
||||
S16 owns PostgreSQL storage of the latest run, atomic persistence of saved
|
||||
assignments and completed status, and startup recovery of previously running
|
||||
calculations as Interrupted without automatic resumption. Previously saved
|
||||
results must survive restart under S16. These are not completion criteria for S12.
|
||||
Distributed execution and scheduling on another PC remain in S13.
|
||||
|
||||
## Out of scope
|
||||
|
||||
- Cancelling a calculation or applying an intermediate solution.
|
||||
- History of earlier calculations beyond the latest status and outcome.
|
||||
- Global capacity limits, queues and remote workers.
|
||||
- Changes to scheduling objectives or constraints.
|
||||
- This specification grants no coding-standards waiver.
|
||||
|
||||
## Acceptance criteria
|
||||
|
||||
- [x] Starting Schedule Groups returns without waiting for solver completion;
|
||||
leaving or reloading the page does not interrupt the calculation.
|
||||
- [x] Opening a show in another screen recovers its current backend status;
|
||||
duplicate runs for the same show are prevented in frontend and backend,
|
||||
while different shows can run concurrently.
|
||||
- [x] Running status shows elapsed time, phase and discovery of a valid solution
|
||||
during a phase, without a fabricated completion percentage or ETA.
|
||||
- [x] SSE delivers status changes promptly through the deployed proxy. Initial
|
||||
connection and reconnection reconcile the current state, and loss of
|
||||
connectivity visibly marks status as potentially outdated.
|
||||
- [x] Successful runs automatically apply their result after the existing start
|
||||
confirmation, retain stale-input protection and distinguish proven optimal
|
||||
results from valid results at the time limit.
|
||||
- [x] The final display includes finish time and concrete attendance, spread and
|
||||
variety results when successful; unsuccessful outcomes are distinguishable
|
||||
and explain that previous assignments were preserved.
|
||||
- [x] An application-wide snackbar reports completion or failure with the show
|
||||
name and View show action, including after navigation to another page.
|
||||
- [x] Connection recovery notifies once for a missed completion; phase changes,
|
||||
repeated reconnection and reopening do not replay old snackbars.
|
||||
- [x] The latest status and outcome survive navigation, page reload and SSE
|
||||
reconnection within the lifetime of the running backend. Durable storage
|
||||
and recovery after backend restart are explicitly transferred to S16.
|
||||
|
||||
## Review handoff
|
||||
|
||||
Background execution, solver progress callbacks, SSE, frontend status recovery,
|
||||
result summaries, proxy streaming configuration and application-wide completion
|
||||
notifications are implemented and verified. S12 replaces S9's synchronous request
|
||||
behavior while retaining scheduling and result-application protections.
|
||||
|
||||
See [S12 validation](http://192.168.2.28:3000/wanjakrah/agiledancers/src/branch/feature/S19_multi-project/docs/validation/S12-validation.md) for verification and retained standards
|
||||
signals. Durable storage and backend-restart recovery are tracked in S16 and do
|
||||
not block review of this specification under the agreed scope adjustment.
|
||||
Implementation is ready for review; final acceptance is pending.
|
||||
|
||||
|
||||
Affected repositories: `agiledancers`.
|
||||
158
specs/implemented/S16_store-state-in-persistent-storage
Normal file
158
specs/implemented/S16_store-state-in-persistent-storage
Normal file
@@ -0,0 +1,158 @@
|
||||
# S16 — Store state in persistent storage
|
||||
|
||||
Status: IMPLEMENTED
|
||||
|
||||
Agreed after the grill-me interview; shared understanding confirmed.
|
||||
|
||||
## User story
|
||||
|
||||
As a dance school maintainer, I want application data to be stored persistently,
|
||||
so that confirmed changes and saved scheduling results survive server restarts
|
||||
and application crashes.
|
||||
|
||||
## Storage decision
|
||||
|
||||
Use PostgreSQL with relational tables for schools, dancers, coaches, groups,
|
||||
shows and their relationships. Use Flyway to version and apply database schema
|
||||
changes. Use JPA with Hibernate ORM for application persistence; keep the mappings
|
||||
inside the repository layer so the existing domain model remains framework independent.
|
||||
|
||||
The existing domain has shared relationships and operations on individual school
|
||||
components. Related changes must be atomic, and multiple maintainers must be able
|
||||
to work without silently overwriting each other's changes. These requirements
|
||||
favor relational storage with transactions and referential constraints.
|
||||
|
||||
A document database was considered: a whole-school document would align with
|
||||
JSON import/export. However, the agreed requirements provide no concrete benefit
|
||||
for that approach over relational storage. The application owns a fixed domain
|
||||
model; school-defined arbitrary fields and structures are not required.
|
||||
|
||||
JSON remains the import/export format, rather than the primary storage model.
|
||||
|
||||
## Scope and deployment
|
||||
|
||||
- Support multiple schools and concurrent maintainers.
|
||||
- Target one production environment with one active backend instance.
|
||||
- A separate database service and its operational management are acceptable.
|
||||
- Multiple active backend instances, distribution across servers or regions, and
|
||||
automatic resumption of calculations are outside S16.
|
||||
- Keep the implementation within existing project architecture and coding
|
||||
standards; this specification grants no standards waiver.
|
||||
|
||||
## Durability and consistency
|
||||
|
||||
- Confirm a mutation as successful only after its database transaction commits
|
||||
durably. All confirmed domain changes and saved scheduling results survive an
|
||||
application restart or crash.
|
||||
- Persist schools and all their maintained domain data, relationships and saved
|
||||
planning state, rather than only a subset of the existing in-memory state.
|
||||
- Related mutations either succeed completely or leave the previous state intact.
|
||||
This includes deleting a dancer and cleaning up memberships, deleting a group
|
||||
and cleaning up show references, deleting a school and its children, and
|
||||
replacing a school through import.
|
||||
- Validate imports before publishing the replacement. Preserve the current
|
||||
import/export behavior and identity semantics.
|
||||
- Enforce valid relationships through database constraints alongside application
|
||||
validation.
|
||||
|
||||
## Concurrent changes and scheduling
|
||||
|
||||
- Use one persistent revision per school for optimistic concurrency control.
|
||||
- Mutations must identify the school revision on which they are based. Check
|
||||
that revision and commit the change and new revision atomically.
|
||||
- Reject stale mutations with a clear conflict message; do not silently overwrite
|
||||
newer changes. The user can reload current data and decide again.
|
||||
- Changes to different components of the same school may therefore conflict.
|
||||
Finer-grained conflict detection is outside S16.
|
||||
- Retain the scheduling input revision check: a result computed from an outdated
|
||||
input revision must not replace current planning state.
|
||||
- After restart, calculations interrupted by the restart must be recognizably
|
||||
interrupted, rather than remain indefinitely marked as running. They do not
|
||||
resume automatically. Previously saved results remain available.
|
||||
|
||||
## Persistent scheduling status (transferred from S12)
|
||||
|
||||
The maintainer explicitly moved durable scheduling status and backend-restart
|
||||
recovery from S12 to S16 when completing S12. S12 supplies background execution,
|
||||
status snapshots, SSE and notifications within the lifetime of the backend.
|
||||
|
||||
- Persist the latest calculation per show in PostgreSQL, including its run
|
||||
identifier, school/show identity, start and finish timestamps, state, latest
|
||||
phase, whether a valid solution was found, outcome explanation and final
|
||||
attendance/spread/variety summary when available. A run history is not required.
|
||||
- Persist acceptance of a run before acknowledging its start. After restart or
|
||||
crash, an accepted calculation must remain identifiable even if it never
|
||||
produced a result.
|
||||
- Commit successful assignment replacement and its completed run status
|
||||
atomically. Publish success through the status API and SSE only after the
|
||||
transaction commits. A failed commit must not leave a successful status with
|
||||
missing assignments, or replaced assignments with an outdated running status.
|
||||
- On startup, mark calculations left Running by the previous backend instance
|
||||
as Interrupted before serving their recovered status. Explain that no new
|
||||
result was applied, retain previously saved assignments and allow a new run.
|
||||
Do not resume calculations automatically or retain their old run-slot guards.
|
||||
- Recover the latest status and outcome through S12's existing status endpoint
|
||||
and initial/reconnection SSE snapshots. Preserve stable run identifiers so
|
||||
reconnecting clients can deduplicate notifications; reopening the application
|
||||
must not replay old completion snackbars.
|
||||
- Verify recovery after both graceful restart and abrupt process termination,
|
||||
including a calculation running at termination and a completed saved result.
|
||||
|
||||
## Database failures and schema changes
|
||||
|
||||
- Refuse mutations while the database is unavailable and provide a clear failure
|
||||
message. Do not acknowledge successful storage or fall back to volatile writes.
|
||||
- Connection and Flyway migration failures at startup must be clearly visible;
|
||||
the application must not present itself as ready for normal use when required
|
||||
database initialization has failed.
|
||||
- Maintain the database schema through versioned Flyway migrations.
|
||||
|
||||
## Transition from in-memory storage
|
||||
|
||||
Start with an empty database. Existing data is transferred through the current
|
||||
JSON export/import path; no separate in-memory migration mechanism is required.
|
||||
Document that existing data must be exported before stopping the old application
|
||||
for the transition, because its current state exists only in memory.
|
||||
|
||||
## Deferred work
|
||||
|
||||
Database backup and restore are outside S16 and will be specified separately in
|
||||
`specs/S17_database-backup-and-restore`. That specification is intentionally empty
|
||||
for now. S16 does not promise recovery after loss of the database or its volume.
|
||||
|
||||
## Acceptance criteria
|
||||
|
||||
- [x] PostgreSQL stores the complete maintained domain state and saved scheduling
|
||||
results, with Flyway managing the relational schema.
|
||||
- [x] Confirmed changes remain available after both a normal restart and an
|
||||
application crash, using the same persistent database.
|
||||
- [x] Failed related mutations and failed school replacement imports leave no
|
||||
partial changes or dangling references.
|
||||
- [x] Two edits based on the same school revision cannot silently overwrite one
|
||||
another: the stale edit receives a clear conflict response, and the user
|
||||
can reload and retry.
|
||||
- [x] Scheduling results based on outdated input revisions are rejected.
|
||||
- [x] The latest accepted scheduling run, its stable identifier, timestamps,
|
||||
progress, outcome and objective summary survive normal restart and crash
|
||||
and are returned through the status API and SSE snapshots.
|
||||
- [x] Successful assignment replacement and completed run status commit
|
||||
atomically; success is published only after durable commit.
|
||||
- [x] Calculations left Running become Interrupted before recovered status is
|
||||
served; previous assignments remain, no automatic resumption occurs and a
|
||||
new run can start. Reopening does not replay old completion snackbars.
|
||||
- [x] Database unavailability prevents successful mutation acknowledgements;
|
||||
startup connection and migration failures are clearly reported.
|
||||
- [x] An empty database can be initialized through Flyway and populated through
|
||||
existing JSON import, preserving import/export behavior and identities.
|
||||
- [x] Setup and transition instructions cover the database service, persistent
|
||||
storage, connection configuration, migrations and export-before-transition.
|
||||
|
||||
## Implementation handoff
|
||||
|
||||
PostgreSQL/JPA/Hibernate storage, Flyway migrations, school revision checks, durable scheduling status and
|
||||
restart recovery are implemented and verified. See [S16 validation](http://192.168.2.28:3000/wanjakrah/agiledancers/src/branch/feature/S19_multi-project/docs/validation/S16-validation.md)
|
||||
and [setup and transition instructions](../../docs/persistent-storage.md).
|
||||
Implementation is ready for review; final acceptance is pending.
|
||||
|
||||
|
||||
Affected repositories: `agiledancers`.
|
||||
@@ -0,0 +1,148 @@
|
||||
# S18 — Scheduling dance groups across a show
|
||||
|
||||
Status: IMPLEMENTED
|
||||
|
||||
As a dance school manager,
|
||||
I want OR-Tools to schedule groups and order performances using participation,
|
||||
changing-time and variety rules,
|
||||
so that the complete show is manageable for dancers and enjoyable for audiences.
|
||||
|
||||
Refinement confirmed by the maintainer on 2026-11-03. This specification records
|
||||
the agreed design. Implementation and validation are complete and ready for review.
|
||||
See [validation evidence](../../docs/s18-validation.md) and
|
||||
[the applied scheduling rules](../../show-scheduling-rules.md).
|
||||
|
||||
## Show scope and configuration
|
||||
|
||||
- A show consists of dayparts and can span multiple dates, typically two days.
|
||||
All counts below apply across the entire show, not separately per date.
|
||||
- Each show has one configurable integer `preferredDayParts`, between 1 and the number of
|
||||
dayparts inclusive. Its default is 2, or 1 for a one-daypart show.
|
||||
- This replaces the existing configurable appearance counts per group type.
|
||||
- A show without dayparts can be stored but cannot be scheduled.
|
||||
- If reducing the number of dayparts makes `preferredDayParts` invalid, require the user to
|
||||
correct it before scheduling again; do not silently change it.
|
||||
- Groups without dancers are excluded from scheduling and from all performance
|
||||
counts and showcase-position requirements.
|
||||
|
||||
## Required group appearances
|
||||
|
||||
- Each nonempty REGULAR, SELECTION and PRE_EDUCATION group performs in exactly
|
||||
`preferredDayParts` distinct dayparts, once within each selected daypart.
|
||||
- Each nonempty PRE_SCHOOLER group performs exactly once in the complete show,
|
||||
regardless of `preferredDayParts`. At most two such groups are expected. They can be assigned
|
||||
freely to dayparts; no additional placement restriction applies.
|
||||
- Each nonempty SHOW_CASE group performs exactly once in every daypart.
|
||||
- With at least two showcase groups, each daypart starts with one showcase and
|
||||
ends with another. Additional showcases can appear anywhere between them.
|
||||
Opening and closing groups may differ between dayparts.
|
||||
- With exactly one showcase group, it appears either first or last in each
|
||||
daypart; the planner chooses. It does not perform twice in that daypart.
|
||||
- With no showcase groups, there is no showcase-position requirement.
|
||||
|
||||
## Dancer participation and coaches
|
||||
|
||||
- A dancer without a showcase membership performs in at most `preferredDayParts` distinct
|
||||
dayparts across the complete show. This is a hard constraint.
|
||||
- A showcase participant necessarily performs in all dayparts. Their other
|
||||
group performances may span more than `preferredDayParts` dayparts, but this is undesirable.
|
||||
- For each non-coach showcase participant, count the distinct dayparts in which
|
||||
they perform outside showcases. Their excess is `max(0, count - preferredDayParts)`.
|
||||
Minimize the sum of these excesses as the first optimization priority.
|
||||
- A person dancing in several groups must use the same dancer registration in
|
||||
every group, including when accompanying preschoolers. Up to five group
|
||||
memberships per dancer are expected.
|
||||
- Explicitly link a coach registration to the corresponding dancer registration;
|
||||
never infer identity from matching names. Support maintaining this link.
|
||||
- Coaches are available in all dayparts and are excluded from both the hard
|
||||
dancer limit and the excess penalty, including coaches in showcases.
|
||||
- Being assigned as a group's coach does not automatically mean performing in
|
||||
that group. Actual performances are determined by dancer membership only.
|
||||
Coach availability never increases a group's required appearances.
|
||||
- Dancing coaches remain subject to changing-time rules and contribute to the
|
||||
group's average age just like other dancing members.
|
||||
|
||||
## Changing time and feasibility
|
||||
|
||||
- Between any two performances involving the same dancer within a daypart,
|
||||
there must be at least two intervening performances not involving that dancer.
|
||||
- This is mandatory for everyone, including coaches and showcase participants.
|
||||
- The rule restarts at each daypart boundary. Assume enough changing time
|
||||
between dayparts, including on the same date.
|
||||
- All hard constraints apply together, even for unusual membership combinations
|
||||
such as a person dancing in both preschool and ordinary groups. Do not relax
|
||||
a rule to obtain a result.
|
||||
|
||||
## Balance and optimization priorities
|
||||
|
||||
- Count all scheduled performances, including preschool and showcase groups.
|
||||
- The difference between the largest and smallest daypart performance counts
|
||||
must not exceed two. This is a hard constraint.
|
||||
- Prefer a difference of zero. Preschool groups are an expected cause of
|
||||
differences but have no special exemption or exclusive right to cause them.
|
||||
- Optimize valid schedules in this strict priority order:
|
||||
1. Minimize the total excess for non-coach showcase participants defined above.
|
||||
2. Minimize the difference between largest and smallest daypart counts.
|
||||
3. Improve style and age variety between consecutive performances within
|
||||
each daypart.
|
||||
- A lower priority must not worsen a higher priority. Showcases participate in
|
||||
variety scoring as well.
|
||||
|
||||
## Variety scoring
|
||||
|
||||
- For adjacent groups, the style penalty is the number of shared styles divided
|
||||
by the number of distinct styles in their combined style sets. No shared
|
||||
styles gives zero penalty; two empty style sets also give zero penalty.
|
||||
- Compute dancer ages on the first date of the show. All dancers in a group,
|
||||
including dancing coaches, contribute equally to its average age.
|
||||
- The age penalty decreases linearly from 1 for equal average ages to 0 for a
|
||||
difference of five years; differences greater than five years also score 0.
|
||||
Equivalently: `max(0, 1 - abs(meanAgeA - meanAgeB) / 5)`.
|
||||
- Style and age penalties have equal weight. Minimize their combined penalties
|
||||
over adjacent performances. Empty groups have already been excluded.
|
||||
|
||||
## Solver execution and failure
|
||||
|
||||
- Retain a maximum solver runtime of thirty minutes.
|
||||
- Accept a feasible result without proof of optimality, provided every hard
|
||||
constraint holds. Distinguish feasibility from proven optimality.
|
||||
- If no valid result is found, preserve the existing assignments and order.
|
||||
- Explain whether infeasibility was proven or the time limit expired without
|
||||
a valid result; do not report a timeout as proof of infeasibility.
|
||||
- Retain existing protections against concurrent scheduling and applying stale
|
||||
results after relevant data changes.
|
||||
|
||||
## Manual editing and schedule lifecycle
|
||||
|
||||
- Add UI and API support for moving performances between dayparts and changing
|
||||
their order. Partial or temporarily invalid assignments can be saved as drafts.
|
||||
- Distinguish draft and final schedules explicitly. Display concrete violations
|
||||
for invalid drafts; do not present them as valid final schedules.
|
||||
- Add an explicit finalization action that checks all hard rules and permits
|
||||
finalization only when they all pass. Optimization preferences do not block it.
|
||||
- Automatically generated valid schedules also start as drafts for manager review.
|
||||
- Manual changes to a final schedule return it to draft. Changes to relevant
|
||||
dancer memberships, coach identity links or show settings likewise invalidate
|
||||
final status when they affect scheduling rules.
|
||||
- Treat existing schedules as drafts when introducing this lifecycle.
|
||||
- JSON import preserves assignments and order but makes imported schedules
|
||||
drafts and validates them against the new rules.
|
||||
- JSON export remains available for drafts and finals and preserves status.
|
||||
Import still produces a draft even when the exported status was final.
|
||||
- Include the new configuration and coach identity information in persistence
|
||||
and school JSON round trips so scheduling semantics survive saving and import.
|
||||
|
||||
## Documentation and validation
|
||||
|
||||
- Provide `show-scheduling-rules.md` describing the rules applied by OR-Tools in
|
||||
plain English, including hard constraints, exceptions, optimization priorities,
|
||||
scoring, cross-date scope and failure behavior.
|
||||
- Validate automatic results and finalization using the same agreed rules.
|
||||
- Verification must cover ordinary, preschool and showcase appearances; coach
|
||||
identity and exemptions; overlapping memberships; changing gaps; balance;
|
||||
optimization priority and scoring; multi-date shows; empty groups; invalid
|
||||
configuration; infeasible and timed-out runs; manual drafts/finalization; and
|
||||
persistence/import/export of the new information.
|
||||
|
||||
|
||||
Affected repositories: `agiledancers`.
|
||||
163
specs/implemented/S1_School-JSON-import-export.md
Normal file
163
specs/implemented/S1_School-JSON-import-export.md
Normal file
@@ -0,0 +1,163 @@
|
||||
# S1 — School JSON import and export
|
||||
|
||||
Status: implemented
|
||||
|
||||
## User story
|
||||
|
||||
**As** a school maintainer,
|
||||
**I want** to export and import my dance school as a JSON file,
|
||||
**so that** I can store my school configuration locally while the application does
|
||||
not offer persistent storage,
|
||||
**and so that** I retain ownership of my data.
|
||||
|
||||
## Intent
|
||||
|
||||
Export downloads a complete snapshot of one dance school to a local JSON file.
|
||||
Import restores that snapshot as a new school or replaces the corresponding
|
||||
existing school after explicit confirmation.
|
||||
|
||||
## Scope
|
||||
|
||||
### In scope
|
||||
|
||||
- Exporting an existing school to a readable JSON file.
|
||||
- Importing a school that does not exist or no longer exists.
|
||||
- Replacing an existing school with the complete imported snapshot.
|
||||
- Preserving all configured school data and relationships, including:
|
||||
- School details and its persistent unique key.
|
||||
- Dancers and their details.
|
||||
- Dance groups, types, age ranges and styles.
|
||||
- Dancer memberships, including dancers belonging to multiple groups.
|
||||
- Shows, dates, day parts and any existing group assignments to day parts.
|
||||
- Coaches and any existing links between coaches and groups.
|
||||
- Full validation, an import preview, confirmation and clear error messages.
|
||||
|
||||
Preserving existing data does not add management screens for coaches or the
|
||||
ability to assign groups to show day parts.
|
||||
|
||||
### Out of scope
|
||||
|
||||
- Merging an imported snapshot with an existing school.
|
||||
- Persistent server-side storage.
|
||||
|
||||
The existing-school prompt includes a merge option, but selecting it only displays
|
||||
that merging is not yet supported. It must not change any data. Implementing merge
|
||||
behavior requires a separate specification.
|
||||
|
||||
## Identity and file format
|
||||
|
||||
- Every school has a persistent unique key that is included in exports and
|
||||
preserved through imports and subsequent exports.
|
||||
- Import identifies an existing school by that key, not by its name or a
|
||||
runtime-generated numeric ID. The key remains meaningful after a server restart.
|
||||
- A school with the same name but a different unique key is a separate school.
|
||||
- A file contains one school and all data needed to restore it without accessing
|
||||
another school or the original server state.
|
||||
- The readable, documented JSON format includes a `formatVersion` field.
|
||||
- Users may edit the JSON manually. Edited files undergo the same validation as
|
||||
files produced by the application.
|
||||
- Unknown fields and unsupported format versions are rejected explicitly; data
|
||||
must not be silently ignored.
|
||||
- Relationships in the file must be unambiguous and restored correctly. Internal
|
||||
numeric IDs need not remain identical, provided school identity and all
|
||||
relationships are preserved without collisions with other schools.
|
||||
|
||||
## Export flow
|
||||
|
||||
1. The maintainer opens an existing school's management screen.
|
||||
2. The maintainer selects the JSON export option.
|
||||
3. The application downloads a JSON file containing a consistent, complete
|
||||
snapshot of that school.
|
||||
4. Export does not change the school or any other application data.
|
||||
|
||||
## Import flow
|
||||
|
||||
1. The maintainer selects the JSON import option and chooses a local file.
|
||||
2. The application validates the entire file before changing any stored data.
|
||||
3. For a valid file, the application shows a preview containing the school name
|
||||
and the numbers of dancers, dance groups and shows.
|
||||
4. If the unique school key is unknown, the maintainer confirms adding the school
|
||||
or cancels the import.
|
||||
5. If the key already exists, the application identifies the school that would be
|
||||
replaced and offers replace, merge or cancel:
|
||||
- **Replace:** explicitly warn that the existing school is replaced completely.
|
||||
After confirmation, replace all its configured data with the snapshot.
|
||||
- **Merge:** show a message that this functionality is not yet supported and
|
||||
leave all data unchanged.
|
||||
- **Cancel:** leave all data unchanged.
|
||||
6. A confirmed import is committed as one operation. The application must not
|
||||
expose a partially imported or partially replaced school.
|
||||
7. If validation or importing fails, show **"Import niet gelukt"** together with
|
||||
the concrete cause. The user can correct the file and try again.
|
||||
|
||||
## Validation and failure behavior
|
||||
|
||||
- Validate JSON syntax, the supported file structure and format version, required
|
||||
data, field values and all relationships before applying the import.
|
||||
- Reject unknown fields and references to missing objects, including a group's
|
||||
reference to a dancer absent from the snapshot.
|
||||
- A failure must not create a partial school, partially replace an existing
|
||||
school, or modify another school.
|
||||
- A replacement must not remove the original school until the complete
|
||||
replacement can succeed. If it fails, the original school remains intact.
|
||||
- Error messages explain the cause specifically enough to correct the file.
|
||||
For example: **"Import niet gelukt: groep Hiphop verwijst naar een onbekende
|
||||
danser."**
|
||||
|
||||
## Acceptance criteria
|
||||
|
||||
### Export
|
||||
|
||||
1. Each existing school offers a JSON-file export that can be downloaded and
|
||||
stored locally.
|
||||
2. The export includes its persistent unique key, `formatVersion`, all configured
|
||||
data listed in scope and all relationships between those objects.
|
||||
3. Exporting leaves the application data unchanged.
|
||||
4. A school with no dancers, groups or shows can be exported and imported.
|
||||
|
||||
### Adding a school
|
||||
|
||||
5. A valid file with an unknown school key shows the preview before any data is
|
||||
added. Confirming creates the complete school; cancelling changes nothing.
|
||||
6. An exported school can be restored after the original school is deleted or
|
||||
the in-memory server state is lost.
|
||||
7. An existing school with the same name but a different key is neither replaced
|
||||
nor treated as the same school.
|
||||
|
||||
### Replacing a school
|
||||
|
||||
8. A valid file with an existing school key prompts the user to replace, merge or
|
||||
cancel and clearly identifies the existing school.
|
||||
9. Confirming replacement replaces the complete configuration. Objects and
|
||||
relationships present only in the previous configuration are not retained as
|
||||
part of the replaced school.
|
||||
10. Other schools remain unchanged by replacement.
|
||||
11. Selecting merge displays that merging is not yet supported and changes
|
||||
nothing. Cancelling also changes nothing.
|
||||
|
||||
### Validation and errors
|
||||
|
||||
12. Malformed JSON, unsupported format versions, unknown fields, missing required
|
||||
data, invalid field values and unresolved relationships cause the entire
|
||||
import to fail.
|
||||
13. Each failed import displays **"Import niet gelukt"** and a concrete cause.
|
||||
14. A failed new-school import adds nothing. A failed replacement preserves the
|
||||
entire existing school. Other schools are unaffected in either case.
|
||||
15. After a failure, the user can select a corrected file and retry.
|
||||
|
||||
### Round-trip integrity
|
||||
|
||||
16. Exporting and importing a school preserves every configured field and
|
||||
relationship, including a dancer's membership in multiple groups, shows and
|
||||
their day parts, and any existing coaches or day-part group assignments.
|
||||
17. Exporting the restored school again preserves its unique school key and
|
||||
equivalent configuration, even if internal numeric IDs changed.
|
||||
|
||||
## Implementation handoff
|
||||
|
||||
This specification records agreed behavior. Backend endpoints, the detailed JSON
|
||||
schema and frontend implementation remain implementation work; this review does
|
||||
not implement the feature.
|
||||
|
||||
|
||||
Affected repositories: `agiledancers`.
|
||||
228
specs/implemented/S2_implement-eslint-for-fe
Normal file
228
specs/implemented/S2_implement-eslint-for-fe
Normal file
@@ -0,0 +1,228 @@
|
||||
# S2 — ESLint for the frontend
|
||||
|
||||
Status: IMPLEMENTED
|
||||
|
||||
Agreed after the grill-me review; shared understanding confirmed.
|
||||
|
||||
## User story
|
||||
|
||||
As a frontend maintainer, I want automated lint checks during development and in
|
||||
CI, so that likely bugs and Angular/TypeScript problems are caught before changes
|
||||
are accepted or application images are published.
|
||||
|
||||
I also want a fast local commit hook where feasible, without losing control of
|
||||
which changes are included in my commit.
|
||||
|
||||
## Scope and boundary with S3
|
||||
|
||||
### In scope
|
||||
|
||||
- Install and configure compatible ESLint, TypeScript and Angular lint tooling.
|
||||
- Apply the recommended JavaScript, TypeScript and Angular rules, including
|
||||
recommended type-aware checks for TypeScript.
|
||||
- Lint maintained frontend application code, external and inline Angular HTML
|
||||
templates, unit tests, Playwright tests and applicable frontend configuration
|
||||
files.
|
||||
- Fix all existing violations of the agreed rules and verify that the application
|
||||
still builds and its tests pass.
|
||||
- Provide local check and autofix commands, mandatory pipeline enforcement,
|
||||
editor support and documentation.
|
||||
- Introduce a staged-file commit hook only if it meets the agreed performance
|
||||
and change-preservation requirements.
|
||||
|
||||
### Out of scope
|
||||
|
||||
- Additional opinionated coding conventions or stricter rule sets beyond the
|
||||
agreed recommended baseline. These belong in S3.
|
||||
- Backend or Java CI-helper linting.
|
||||
- Linting dependencies, generated output or generated files such as
|
||||
`package-lock.json`.
|
||||
- A new mandatory Prettier check in CI. Prettier remains the formatting tool;
|
||||
this spec adds its local commit-hook use only when the timing budget permits.
|
||||
|
||||
## Existing environment
|
||||
|
||||
The reviewed frontend uses Angular 22.2.3, Angular CLI/build 22.2.4, TypeScript
|
||||
6.0.3 and Prettier 3.9.10. TypeScript strict mode and Angular strict-template
|
||||
checking are already enabled. Prettier configuration already exists.
|
||||
|
||||
No ESLint configuration, lint command or active Git commit hook was present at
|
||||
review. The frontend package is in `agiledancers-fe/`, below the Git root.
|
||||
Implementation must account for that layout when installing repository hooks.
|
||||
|
||||
Choose versions compatible with the installed Angular CLI and TypeScript. Use
|
||||
supported configuration for those versions rather than copying incompatible
|
||||
examples or changing framework versions merely to introduce linting.
|
||||
|
||||
## Lint commands and rule behavior
|
||||
|
||||
- `npm run lint`, executed from `agiledancers-fe/`, checks the entire maintained
|
||||
frontend scope without changing files.
|
||||
- A lint error or warning causes a nonzero exit status. A successful check means
|
||||
there are no outstanding ESLint errors or warnings.
|
||||
- `npm run lint:fix` is an explicit local command that applies supported ESLint
|
||||
autofixes. Developers review its changes and resolve any remaining findings.
|
||||
- CI uses the checking command only and must not repair, format, stage or commit
|
||||
source changes itself.
|
||||
- Keep formatting under the existing Prettier configuration. Do not introduce
|
||||
conflicting ESLint formatting rules or redefine formatting conventions in S2.
|
||||
- Narrow exceptions are permitted when a rule is demonstrably unsuitable. Each
|
||||
suppression has a concrete explanation and the smallest applicable scope.
|
||||
Do not broadly disable rules merely to avoid investigating existing findings.
|
||||
- Start with a clean baseline: do not introduce a legacy-violation allowance,
|
||||
warning backlog or ignored maintained files to make the initial check pass.
|
||||
- Fixes preserve application behavior; builds and tests must still pass.
|
||||
|
||||
## Pipeline integration
|
||||
|
||||
Every branch pipeline must run `npm run lint` immediately after frontend
|
||||
`npm ci`, before frontend tests, frontend builds and container end-to-end tests.
|
||||
|
||||
A failed lint check fails the pipeline and prevents image publication. Its
|
||||
concrete findings must be visible in the job log and retained in the existing
|
||||
pipeline diagnostics. The local hook never replaces the full pipeline check.
|
||||
|
||||
Integrate this into the existing Java-based pipeline orchestration. Repository
|
||||
hook installation is skipped during CI and Docker package installation.
|
||||
|
||||
## Editor support
|
||||
|
||||
Recommend the ESLint extension in the existing VS Code project recommendations.
|
||||
Do not require automatic fixing or formatting on save. Document how developers
|
||||
can see findings while editing and run the same check as CI.
|
||||
|
||||
## Local commit hook
|
||||
|
||||
### File selection and tools
|
||||
|
||||
- Only process maintained frontend files staged for the current commit.
|
||||
- Skip frontend checks for commits without applicable staged frontend changes.
|
||||
- ESLint only checks; it does not autofix in the hook. Errors and warnings block
|
||||
the commit if ESLint is part of the selected hook configuration.
|
||||
- Prettier may format maintained frontend TypeScript, JavaScript, HTML, CSS and
|
||||
JSON configuration files and stage the formatting result automatically.
|
||||
- Exclude dependencies, build output and generated files such as
|
||||
`package-lock.json`.
|
||||
- If both tools are included, format with Prettier before checking the result
|
||||
with ESLint. Do not run modifying operations concurrently on overlapping files.
|
||||
|
||||
### Preserve the intended commit
|
||||
|
||||
- Support partially staged files: format the version intended for the commit
|
||||
while preserving unrelated unstaged changes.
|
||||
- Automatically staging formatting must not include unrelated local edits or
|
||||
change which unrelated files are committed.
|
||||
- On any hook failure, including an ESLint failure after successful formatting,
|
||||
abort the commit and restore the original staged and unstaged state.
|
||||
- A conflict while reconciling formatting with unstaged edits also aborts the
|
||||
commit and restores the original state.
|
||||
- Report a concrete cause when the hook fails. Do not leave partial formatter,
|
||||
staging or temporary-state changes behind.
|
||||
- Use tooling that supports this behavior with its state-preservation protections
|
||||
enabled; the specific hook manager/staged-file runner is an implementation
|
||||
choice.
|
||||
|
||||
### Three-second performance budget
|
||||
|
||||
The budget covers the entire additional hook duration, including file selection,
|
||||
backup/state handling, tool startup, formatting/checking, restaging and cleanup.
|
||||
It is a combined budget, not three seconds per tool.
|
||||
|
||||
Measure the actual complete hook on the existing development mini-PC for:
|
||||
|
||||
1. A single applicable staged frontend file.
|
||||
2. A mixed commit containing applicable frontend file types.
|
||||
3. All maintained frontend files staged together.
|
||||
|
||||
Use a newly started process and no tool cache for each measured execution,
|
||||
including cold tool starts. Every measured execution must finish within three
|
||||
seconds. Record the machine/environment, exact staged scope, commands and timing
|
||||
results in the implementation evidence. Do not claim the budget based only on
|
||||
warm cached executions or timings of an individual tool.
|
||||
|
||||
Choose the hook configuration from those measurements:
|
||||
|
||||
1. Include Prettier and ESLint if the combined complete hook meets the budget.
|
||||
2. Otherwise omit ESLint from the hook and measure the complete Prettier-only
|
||||
hook against the same budget and scenarios.
|
||||
3. If Prettier-only also fails the budget, do not install an active commit hook.
|
||||
|
||||
Do not enforce the budget by killing a writing formatter mid-operation. It is an
|
||||
acceptance criterion for selecting the hook configuration, not a hard runtime
|
||||
interrupt that risks incomplete changes. The full type-aware ESLint check remains
|
||||
mandatory in CI regardless of the selected local hook configuration.
|
||||
|
||||
### Installation and operation
|
||||
|
||||
If a hook configuration meets the budget, set it up automatically during local
|
||||
`npm ci`. Skip installation in CI and Docker builds. Document the selected tools,
|
||||
installation behavior and how a developer can disable the local hook.
|
||||
|
||||
If no hook configuration meets the budget, document that result and its timing
|
||||
evidence. Local lint commands and mandatory pipeline enforcement still apply.
|
||||
|
||||
## Documentation
|
||||
|
||||
Add an explanation to the root `README.md` for both `npm run lint` and
|
||||
`npm run lint:fix`, including:
|
||||
|
||||
- Run the commands from `agiledancers-fe/`.
|
||||
- What each command checks or changes and the difference between checking and
|
||||
autofixing.
|
||||
- That errors and warnings fail the checking command, and autofix may leave
|
||||
findings requiring manual changes.
|
||||
- That the pipeline runs the check and blocks publication on failure.
|
||||
- The selected hook behavior, its measured performance and any omitted checks.
|
||||
- Automatic local installation, exclusion from CI/Docker installation, and local
|
||||
opt-out instructions if a hook is installed.
|
||||
- Prettier formatting/restaging and preservation of partially staged files,
|
||||
including restoration on hook failure, when applicable.
|
||||
|
||||
The frontend README may link to the root explanation to keep instructions
|
||||
consistent. Record the performance evidence with the implementation documentation.
|
||||
|
||||
## Acceptance criteria
|
||||
|
||||
- [x] Compatible tooling checks maintained application TypeScript/JavaScript,
|
||||
Angular templates, unit tests, Playwright tests and applicable frontend
|
||||
configuration using the agreed recommended and type-aware rules.
|
||||
- [x] All existing violations are fixed; there is no legacy baseline allowance.
|
||||
Frontend builds, unit tests and container end-to-end tests still pass.
|
||||
- [x] `npm run lint` checks the full scope without modifications and fails on
|
||||
either errors or warnings.
|
||||
- [x] `npm run lint:fix` offers explicit local autofixes; CI does not modify source.
|
||||
- [x] Formatting remains under Prettier, without conflicting ESLint rules.
|
||||
- [x] Any necessary rule suppressions are narrow and concretely justified.
|
||||
- [x] Every branch pipeline runs lint immediately after frontend `npm ci` and
|
||||
before frontend tests/builds and container E2E; lint failure prevents
|
||||
publication and leaves actionable diagnostic output.
|
||||
- [x] VS Code recommends ESLint without mandatory fix/format-on-save settings.
|
||||
- [x] Complete-hook measurements cover the agreed single-file, mixed-file and
|
||||
all-maintained-files cases with fresh processes and no tool cache.
|
||||
- [x] The measured three-second budget determines combined tools, Prettier-only
|
||||
or no active hook; no writing formatter is forcibly interrupted to meet it.
|
||||
- [x] If installed, the hook processes only applicable staged frontend files,
|
||||
applies Prettier formatting before any ESLint check, and preserves unrelated
|
||||
files and unstaged edits, including partially staged files.
|
||||
- [x] A failed installed hook restores the original staged and unstaged state and
|
||||
blocks the commit with a concrete explanation.
|
||||
- [x] Hook installation is automatic for local `npm ci` when applicable, skipped
|
||||
in CI/Docker, and has documented local opt-out instructions.
|
||||
- [x] Root `README.md` explains `npm run lint`, `npm run lint:fix`, CI enforcement
|
||||
and the selected hook behavior; measurement evidence is included.
|
||||
|
||||
## Implementation handoff
|
||||
|
||||
The agreed behavior has been implemented and is ready for review. See the
|
||||
implementation evidence below.
|
||||
|
||||
## Implementation evidence
|
||||
|
||||
Implemented with ESLint flat configuration, type-aware TypeScript and Angular
|
||||
template checks. The measured three-second budget selects a Prettier-only
|
||||
Husky/lint-staged hook; ESLint remains mandatory in the Java-based pipeline.
|
||||
See [validation and timings](../../docs/s2-validation.md) for scope, preservation
|
||||
checks, local installation and successful builds/unit/container E2E tests.
|
||||
|
||||
|
||||
Affected repositories: `agiledancers`.
|
||||
203
specs/implemented/S4_create-build-pipeline-at-gitea
Normal file
203
specs/implemented/S4_create-build-pipeline-at-gitea
Normal file
@@ -0,0 +1,203 @@
|
||||
# S4 — Build and publish pipelines in Gitea
|
||||
|
||||
Status: IMPLEMENTED
|
||||
|
||||
Agreed after the grill-me review; shared understanding confirmed.
|
||||
|
||||
## User story
|
||||
|
||||
As a maintainer, I want every branch push to build and test the application,
|
||||
so that broken changes are detected and successful main-branch builds provide
|
||||
identifiable Docker images in our own registry.
|
||||
|
||||
## Agreed environment and feasibility
|
||||
|
||||
- Gitea and its container registry run on the existing Synology.
|
||||
- The existing development mini-PC runs the Gitea Actions runner, separately from
|
||||
Gitea. No additional hardware is available or required.
|
||||
- Gitea supports push-triggered Actions workflows and a runner on a separate
|
||||
machine. Codex can implement the repository configuration and assist with the
|
||||
installation and configuration required on the existing machines.
|
||||
- Gitea was inspected as version 1.25.4. Match the runner and workflow setup to
|
||||
the installed version rather than assuming newer documentation applies.
|
||||
- The mini-PC was inspected as Linux x86_64 with a Docker client installed, but
|
||||
without a reachable Docker daemon. Configuring a working daemon is part of S4.
|
||||
- The current internal Gitea/registry endpoint is `http://192.168.2.28:3000`.
|
||||
Use that endpoint over the trusted internal network and explicitly configure
|
||||
Docker clients that need registry access to trust this particular HTTP registry.
|
||||
Introducing HTTPS is outside S4.
|
||||
- The runner and job containers need access to Gitea, the registry and dependency
|
||||
download sources. The runner connects to Gitea; it needs no public incoming port.
|
||||
- The mini-PC must be on, awake and running the runner. Jobs wait while it is
|
||||
unavailable; S4 does not promise unattended availability when the PC is off.
|
||||
|
||||
References:
|
||||
|
||||
- [Gitea 1.25 Actions quickstart](https://docs.gitea.com/1.25/usage/actions/quickstart/)
|
||||
- [Gitea 1.25 Actions design](https://docs.gitea.com/1.25/usage/actions/design/)
|
||||
- [Gitea container registry](https://docs.gitea.com/usage/packages/container/)
|
||||
|
||||
## Scope
|
||||
|
||||
### In scope
|
||||
|
||||
- Version-controlled Gitea Actions workflows and supporting build configuration.
|
||||
- Enable Actions as needed at instance and repository level, configure Docker on
|
||||
the mini-PC, and install, register and configure its runner.
|
||||
- Build and test both backend and frontend for every push to every branch,
|
||||
including newly created branches, except when the author intentionally uses a
|
||||
supported skip marker such as `[skip ci]`. Separate tag and pull-request event workflows
|
||||
are not required; branch pushes also check changes used in pull requests.
|
||||
- Build two runnable Docker images: backend and frontend.
|
||||
- Run end-to-end tests against those built containers before publication.
|
||||
- Publish both images only from successful builds of the `main` branch to the
|
||||
container registry on the Synology.
|
||||
- Configure registry authentication and the necessary secrets outside Git.
|
||||
- Preserve failure diagnostics and document operation and recovery.
|
||||
- Demonstrate a real successful pipeline and images that can be pulled back.
|
||||
|
||||
### Out of scope
|
||||
|
||||
- Automatic deployment, starting application containers on the Synology, and OTAP.
|
||||
Starting temporary containers for pipeline tests is in scope.
|
||||
- New linting or static-analysis gates, such as ESLint or Sonar. Existing tests,
|
||||
including architecture tests, remain mandatory.
|
||||
- Merge or release policies, separate tag/release workflows, and automatic image
|
||||
deletion or retention cleanup. Published images remain available for now.
|
||||
- Multi-architecture images, HTTPS setup, new hardware or provisioning additional
|
||||
infrastructure.
|
||||
|
||||
## Build and verification behavior
|
||||
|
||||
1. Every ordinary branch push runs backend and frontend builds and their existing
|
||||
tests. Explicit Gitea-supported skip markers are an accepted maintainer-approved
|
||||
opt-out.
|
||||
2. Backend verification includes the existing unit, integration/system and
|
||||
architecture tests. Current entry point: `mvn clean verify` using Java 25.
|
||||
3. Frontend verification uses the lockfile (`npm ci`), unit tests (`npm test`) and
|
||||
production build (`npm run build`) with a supported Node version.
|
||||
4. Build both Docker images on every branch, including branches that cannot
|
||||
publish. The current Dockerfile only covers the backend; frontend packaging
|
||||
must be added as part of implementation.
|
||||
5. The frontend image serves the production Angular build, supports direct SPA
|
||||
route navigation, and forwards `/api` requests to the backend container.
|
||||
Container addressing/configuration is an implementation choice.
|
||||
6. Run the existing Playwright end-to-end suite with Chromium against the built
|
||||
frontend/backend containers, through the frontend's API forwarding. Adapt the
|
||||
existing development-server test configuration as necessary: the acceptance
|
||||
run must exercise the actual images, not development servers.
|
||||
7. Determine the intended server's CPU architecture during implementation. Build
|
||||
for that single target architecture and run the end-to-end tests on that same
|
||||
architecture. Do not infer the Synology's architecture from the mini-PC.
|
||||
Any architecture mismatch must be resolved and tested on the existing hardware
|
||||
before claiming acceptance.
|
||||
8. A failed build or test fails the pipeline and prevents publication. Test
|
||||
containers are temporary and are cleaned up after the run, including failure.
|
||||
|
||||
## Publication and image identity
|
||||
|
||||
- Publish separate backend and frontend images under the repository owner's
|
||||
namespace in the existing Gitea container registry. Document the exact names.
|
||||
- Feature branches must not publish application images.
|
||||
- Both images from a main-branch commit use the full Git commit SHA as their tag.
|
||||
This identifies the matching pair independently of moving tags.
|
||||
- Once both commit images have been successfully published, reruns verify/reuse
|
||||
them without overwriting either commit tag.
|
||||
- Publication succeeds only when both images are published and can be pulled
|
||||
back from the registry. A partial publication fails the pipeline; one image may
|
||||
already exist. A rerun preserves that image and may publish the missing image.
|
||||
- After both commit images are available, update the moving `main` tags only if
|
||||
the commit is still the current main-branch head. Serialize/coordinate that
|
||||
operation so an older, slower pipeline cannot move `main` backwards.
|
||||
- The two moving tags are not an atomic pair. Use the same commit SHA on both
|
||||
images when an exact matching pair is needed. A failure updating a moving tag
|
||||
must be visible as a pipeline failure and recoverable through a rerun.
|
||||
- No automatic deletion of published images is introduced in S4.
|
||||
|
||||
## Failure diagnostics and operation
|
||||
|
||||
- Failed pipelines retain available test reports, container logs, and Playwright
|
||||
traces and screenshots for fourteen days. Collect available diagnostics even
|
||||
when a preceding step fails; do not hide the original failure.
|
||||
- Provide a short management guide covering:
|
||||
- Docker/runner installation, registration, startup and required access.
|
||||
- Gitea instance/repository Actions settings and registry configuration.
|
||||
- Required credentials, permissions and secret names, without secret values.
|
||||
- Which settings exist outside Git and how to reproduce them.
|
||||
- Trigger behavior, mini-PC availability and queued jobs.
|
||||
- Image names, tags and commands to pull a matching image pair.
|
||||
- Finding diagnostics, rerunning failed jobs and completing partial publication.
|
||||
- The target architecture and how it was established.
|
||||
- Keep registry credentials and registration tokens out of repository files and
|
||||
logs; use the relevant secret settings.
|
||||
|
||||
## Acceptance criteria
|
||||
|
||||
- [x] A push to any branch, including a new branch, starts a pipeline, except for
|
||||
an explicit supported skip marker chosen by the author.
|
||||
- [x] Backend and frontend build and all existing tests, including architecture
|
||||
and Playwright end-to-end tests, pass before publication is permitted.
|
||||
- [x] Every branch builds both Docker images; end-to-end tests exercise those
|
||||
images through the frontend and its `/api` forwarding.
|
||||
- [x] A failing build or test fails the pipeline without publishing images.
|
||||
- [x] A successful feature-branch pipeline publishes no application images.
|
||||
- [x] A successful `main` pipeline publishes both images to the Synology registry
|
||||
with the full commit SHA; both images can be pulled back.
|
||||
- [x] Published commit images are preserved on rerun; partial publication can be
|
||||
completed without overwriting an existing commit image.
|
||||
- [x] Moving `main` tags are updated only after both commit images are available,
|
||||
and an older pipeline cannot move them backwards.
|
||||
- [x] Publication or pull-verification failure makes the pipeline fail, even if
|
||||
some images have already been uploaded.
|
||||
- [x] Available failure diagnostics are retained for fourteen days, and temporary
|
||||
test containers are cleaned up on success and failure.
|
||||
- [x] The runner operates on the existing mini-PC, with Gitea and the registry on
|
||||
the existing Synology; no additional hardware is needed.
|
||||
- [x] The single target architecture is established and the images are tested on
|
||||
that architecture using the existing hardware.
|
||||
- [x] A management guide records setup, external settings, secrets, image usage
|
||||
and recovery, including the need to keep the mini-PC/runner available.
|
||||
- [x] Actual pipeline runs demonstrate successful main-branch publication,
|
||||
feature-branch checks without publication, and failure blocking publication.
|
||||
|
||||
## Implementation handoff
|
||||
|
||||
This specification captures the agreed design. It does not install the runner,
|
||||
change server settings or implement the pipeline. S4 is complete only when the
|
||||
configuration, documentation and operational acceptance evidence are delivered;
|
||||
workflow files alone are insufficient.
|
||||
|
||||
|
||||
## Implementation progress
|
||||
|
||||
Repository implementation and local Docker verification are available. See
|
||||
[management instructions](../../docs/gitea-ci.md) and
|
||||
[validation evidence](../../docs/s4-validation.md).
|
||||
|
||||
Backend verification (20 tests), frontend verification (14 tests), both runtime
|
||||
image builds and both Playwright tests against the containers passed. Fifteen
|
||||
Java CI publication/configuration tests pass. The runner binary and user-service
|
||||
configuration are installed on the mini-PC.
|
||||
|
||||
The maintainer confirmed the Synology as `x86_64` / `linux/amd64`. Gitea secrets
|
||||
and the target-platform variable are configured; the runner is registered and
|
||||
online. Registry login succeeded. Real feature runs #1 and #3 passed, including
|
||||
container E2E; deliberate failure run #2 blocked the build/publication path and
|
||||
provided downloadable diagnostics.
|
||||
|
||||
PR #1 was subsequently merged by the maintainer. Main run #7 succeeded for
|
||||
commit `2356a31aa612c8b0ce4b386a0a65da6589e23285`, publishing and pulling both
|
||||
full-SHA images and both main aliases. Registry digests are recorded in the
|
||||
validation evidence.
|
||||
|
||||
The final real-registry probes confirmed partial-publication recovery, immutable
|
||||
commit-tag preservation on rerun and stale-main protection in isolated validation
|
||||
repositories. Application manifests remained unchanged. The maintainer confirmed
|
||||
that the Synology app.ini has no actions section, so Gitea 1.25.4's documented
|
||||
90-day artifact and 365-day log defaults apply; the workflow requests fourteen
|
||||
days for diagnostic artifacts. Explicit skip markers are accepted by the
|
||||
maintainer. All acceptance criteria are met; see the validation evidence for
|
||||
probe details, digests and the distinction from full Gitea workflow reruns.
|
||||
|
||||
|
||||
Affected repositories: `agiledancers`.
|
||||
191
specs/implemented/S6_deployment-gitea-action-to-production.md
Normal file
191
specs/implemented/S6_deployment-gitea-action-to-production.md
Normal file
@@ -0,0 +1,191 @@
|
||||
# S6 — Manual versioned production deployment through Gitea
|
||||
|
||||
Status: IMPLEMENTED
|
||||
|
||||
Agreed after the grill-me interview; shared understanding confirmed.
|
||||
|
||||
## User story
|
||||
|
||||
As a developer, I want to manually release a verified main-branch build from
|
||||
Gitea to the Synology, choosing a semantic version increment, so that I control
|
||||
when the launching partner receives a new production version and can recover
|
||||
the previous working version when necessary.
|
||||
|
||||
This replaces the original automatic-deployment story. Build, test and image
|
||||
publication remain automatic; production deployment requires a deliberate action.
|
||||
|
||||
## Existing foundation and scope
|
||||
|
||||
- Extend the implemented S4 pipeline, which verifies builds and publishes matching
|
||||
frontend/backend images with immutable full commit SHA tags for successful main
|
||||
builds. Deploy those existing images without rebuilding them.
|
||||
- Target one production Docker Compose stack on the Synology (`linux/amd64`).
|
||||
The existing Gitea runner triggers deployment over SSH.
|
||||
- Keep one active backend. A brief restart interruption is acceptable, including
|
||||
interruption of a scheduling calculation; the user may restart the calculation.
|
||||
- Production is private to the LAN or existing VPN. A configurable Synology
|
||||
hostname/IP and port provide access without an application login.
|
||||
- Publish only the frontend port. Keep the backend reachable within the Compose
|
||||
network; route browser API requests through the frontend proxy.
|
||||
- Actual server addresses, ports, paths and account configuration must be
|
||||
established and documented during implementation, without committing secrets.
|
||||
|
||||
## Manual release interface
|
||||
|
||||
Provide a separate **Deploy production** workflow using Gitea's native manual
|
||||
workflow trigger (`workflow_dispatch`). Its Run workflow popup offers:
|
||||
|
||||
- **New release** or **Retry release** mode.
|
||||
- For a new release: a release-type choice of **patch**, **minor** or **major**.
|
||||
- For a retry: the existing release version tag.
|
||||
|
||||
Provide a manual rollback action for the previous successful production release.
|
||||
The native Gitea button need not be renamed or embedded into an existing build
|
||||
run. Gitea 1.25.4 supports the required modal and choice inputs.
|
||||
|
||||
### New release eligibility and ordering
|
||||
|
||||
- Run the release workflow from main. Branch builds cannot deploy production.
|
||||
- Pin the current main SHA at workflow start. Require successful build checks and
|
||||
image publication for that exact SHA; missing or failed verification leaves
|
||||
production unchanged. Both images must be retrievable before replacement.
|
||||
- Recheck main immediately before changing production. If it has advanced, abort
|
||||
without changing production. Once replacement starts, finish deployment or
|
||||
recovery using the pinned SHA; later commits require another manual release.
|
||||
- Serialize deployment, recovery, rollback, version allocation and tag creation.
|
||||
Prevent stale runs from replacing newer successful production releases.
|
||||
- Reject a new release for an already release-tagged commit and direct the
|
||||
operator to retry or rollback instead. Repeated clicks must not create extra
|
||||
versions or deploy out of order.
|
||||
|
||||
## Semantic versioning and Git tags
|
||||
|
||||
- Use one shared application version for frontend and backend, represented by
|
||||
an immutable annotated Git tag `vMAJOR.MINOR.PATCH` on the verified SHA.
|
||||
- The first release is `v1.0.0`. Inspect remote tags before initialization and
|
||||
fail visibly on conflicting existing history instead of overwriting it.
|
||||
- Subsequent releases increment the highest existing release version tag,
|
||||
including tags belonging to failed deployments. A rollback does not lower the
|
||||
version baseline. Patch increments PATCH; minor increments MINOR and resets
|
||||
PATCH; major increments MAJOR and resets MINOR and PATCH.
|
||||
- For example, from `v1.2.3`, the choices produce `v1.2.4`, `v1.3.0` or `v2.0.0`.
|
||||
- After checking eligibility and image availability, create the tag before
|
||||
changing production. This establishes tag-writing access before replacement.
|
||||
Never move a release tag or reuse its version for different code.
|
||||
- Retain a tag if deployment subsequently fails or aborts. Record the outcome so
|
||||
a tag is not mistaken for proof of successful production deployment.
|
||||
- A retry reuses the existing tag and exact SHA without allocating a version.
|
||||
Require successful build verification and matching available images. Retrying
|
||||
an older release must not supersede a newer successful release. Retrying an
|
||||
existing release is an explicit exception to the current-main requirement.
|
||||
- Rollback restores an existing release and creates no new version. It is an
|
||||
explicit exception to the prohibition on replacing newer code with older code.
|
||||
- Continue using SHA-tagged container images; the Git release tag and deployment
|
||||
record map the semantic version to that SHA and image pair.
|
||||
- Maven/npm version fields and automated changelog generation are outside S6.
|
||||
Do not introduce a version-bump commit and rebuild into the release path.
|
||||
|
||||
## Deployment checks and recovery
|
||||
|
||||
- Retrieve the candidate images and validate prerequisites before replacing the
|
||||
running release. Frontend and backend must use the same selected commit SHA.
|
||||
- Within five minutes of starting the replacement, require all of:
|
||||
- Backend readiness succeeds.
|
||||
- The frontend page is served.
|
||||
- A read-only API request succeeds through the frontend proxy.
|
||||
- Both running containers match the selected SHA/image pair.
|
||||
- Checks must not create or modify user data. Log the selected SHA/version and
|
||||
final outcome.
|
||||
- A failed candidate automatically restores the previous successful image pair
|
||||
and checks its health. The workflow remains failed even if recovery succeeds.
|
||||
- Retain references to the current and previous successful releases and ensure
|
||||
their images remain available. A manual rollback targets that previous release;
|
||||
fail before modifying production if its required images cannot be retrieved.
|
||||
- If the first deployment fails with no previous release, or recovery itself
|
||||
fails, stop with a clear failure report and manual recovery instructions.
|
||||
Preserve diagnostics; do not enter an endless deployment/recovery loop.
|
||||
- Record successful production release state separately from allocated Git tags,
|
||||
so failed attempts do not become the rollback target.
|
||||
|
||||
## Data policy and S16/S17 boundaries
|
||||
|
||||
S16 is **not a prerequisite** for S6. Until S16 is implemented, application state
|
||||
is held in memory and may be lost during deployment, rollback or recovery. The
|
||||
launching-partner phase explicitly accepts this limitation. Restoring old images
|
||||
does not restore lost data.
|
||||
|
||||
- State the temporary data-loss limitation in the workflow description and
|
||||
deployment runbook. The operator is responsible for informing the launching
|
||||
partner; do not add a further approval step to each deployment.
|
||||
- After S16 is implemented, deployments and rollbacks must preserve saved data.
|
||||
Keep persistent storage outside replaceable containers and do not delete it
|
||||
during deployment or recovery.
|
||||
- After S16, ordinary release and rollback paths require database compatibility
|
||||
with the previous application version. Incompatible migrations require a
|
||||
separately planned maintenance procedure; image rollback cannot undo them.
|
||||
- Database backup and restore remain separate S17 work. S6 does not promise
|
||||
recovery of data lost before persistence or through storage loss.
|
||||
|
||||
## Credentials and operational documentation
|
||||
|
||||
- Use a dedicated Synology deployment account with SSH key authentication and a
|
||||
pinned server host key. Document the narrowly required deployment permissions.
|
||||
- Use a separate registry credential with pull access for production and a
|
||||
credential with the required repository permission for release-tag creation.
|
||||
- Store deployment secrets in Gitea Actions secrets, provision server-side
|
||||
credentials securely where needed, and keep secret values out of Git and logs.
|
||||
- Document initial provisioning, configuration, release/retry/rollback operation,
|
||||
credential setup, health checks, release records and manual recovery.
|
||||
- Retain deployment diagnostics for fourteen days, including failed deployment
|
||||
and recovery outcomes, without exposing credentials.
|
||||
|
||||
## Acceptance criteria
|
||||
|
||||
- [x] Successful main builds still automatically verify and publish matching SHA
|
||||
images; publishing does not automatically change production.
|
||||
- [x] Gitea's manual workflow form provides new/retry mode and the appropriate
|
||||
release-type or existing-tag inputs; invalid combinations fail clearly.
|
||||
- [x] The first release and subsequent patch/minor/major releases allocate the
|
||||
agreed versions and immutable annotated remote Git tags on verified SHAs.
|
||||
- [x] Duplicate new releases, tag conflicts, concurrent attempts, stale main
|
||||
snapshots and older pending deployments cannot overwrite release identity
|
||||
or replace a newer successful release.
|
||||
- [x] An unverified release or missing image is rejected before production changes;
|
||||
branch builds cannot deploy production.
|
||||
- [x] A real Synology deployment serves the frontend and proxied API over the
|
||||
private endpoint, with both containers running the selected image pair.
|
||||
- [x] Readiness, frontend, proxied read-only API and image-identity checks establish
|
||||
success within five minutes or trigger recovery.
|
||||
- [x] A deliberately failed release restores the previous successful version,
|
||||
while the workflow reports failure. Failed first deployment and failed
|
||||
recovery produce actionable diagnostics and manual recovery instructions.
|
||||
- [x] A failed release can be retried with its existing tag/SHA without allocating
|
||||
another version or superseding a newer successful release.
|
||||
- [x] Manual rollback demonstrably restores the previous successful release with
|
||||
no new version, and required retained images are available.
|
||||
- [x] The temporary pre-S16 data-loss policy is visible in workflow documentation
|
||||
and the runbook. Once S16 applies, demonstrate saved data surviving both
|
||||
deployment and rollback, including the migration compatibility requirement.
|
||||
The latter is conditional S16 acceptance and is not applicable yet.
|
||||
- [x] Server setup and operational recovery documentation are usable; diagnostics
|
||||
and release outcomes are retained for fourteen days without secrets.
|
||||
|
||||
## Implementation and evidence
|
||||
|
||||
This specification records the confirmed design. The evidence combines automated
|
||||
behavior tests, real Gitea production release/guard runs and isolated real NAS
|
||||
fault tests. Their distinct scopes and the virtual-tag boundary of the isolated
|
||||
tests are documented in `docs/s6-validation.md`. Configuration alone does not
|
||||
complete S6.
|
||||
|
||||
Implementation PR #12 is merged. Production `v1.0.0` runs at
|
||||
`http://192.168.2.28:8088` following a successful main build and real manual Gitea
|
||||
deployment. Native duplicate/branch guards and downloadable artifacts were
|
||||
verified. Twelve isolated real NAS checks cover recovery, retry, distinct-version
|
||||
rollback, failure guards and manual recovery; they use separate state/containers
|
||||
and virtual test tags, without changing production. The test resources have been
|
||||
removed. See `docs/s6-validation.md` for run links, digests, evidence boundaries
|
||||
and the conditional S16 data-persistence acceptance. S6 is ready for review.
|
||||
|
||||
|
||||
Affected repositories: `agiledancers`.
|
||||
214
specs/implemented/S7_define-coding-standards-to-be
Normal file
214
specs/implemented/S7_define-coding-standards-to-be
Normal file
@@ -0,0 +1,214 @@
|
||||
# S7 — Backend coding standards
|
||||
|
||||
Status: IMPLEMENTED
|
||||
|
||||
Shared understanding confirmed after the grill-me review.
|
||||
|
||||
## User story
|
||||
|
||||
As a developer, I want developers and agents to follow explicit coding standards
|
||||
for `agiledancers-be`, so that the code stays readable and maintainable.
|
||||
|
||||
## Scope and authority
|
||||
|
||||
- Create root `CODING_STANDARDS.md` with the complete agreed backend rules.
|
||||
Preserve any existing frontend instructions.
|
||||
- Cover handwritten production and test Java in `agiledancers-be`. Exclude
|
||||
generated code. Dependency injection and production architecture rules apply
|
||||
where relevant. Frontend and Java helpers outside the backend are out of scope.
|
||||
- Use https://www.geeksforgeeks.org/java/coding-guidelines-in-java/ as source
|
||||
material, not as a changing normative dependency. The local document is complete
|
||||
and authoritative for the adopted rules.
|
||||
- The project's pinned Palantir formatter wins formatting conflicts, including
|
||||
comment layout. S8 remains responsible for formatter integration.
|
||||
- Do not adopt unrelated static-analysis rule bundles.
|
||||
|
||||
## Java conventions
|
||||
|
||||
- Types use UpperCamelCase; methods and variables use lowerCamelCase; constants
|
||||
use UPPER_SNAKE_CASE; package names are lowercase.
|
||||
- One top-level type per file; explicit member visibility; `@Override` on
|
||||
overriding methods. Do not invent visibility modifiers where Java forbids them.
|
||||
- Opening braces stay on the declaration/control-statement line. All `if`, `for`
|
||||
and `while` bodies require braces, including enhanced for and do/while bodies.
|
||||
- No wildcard imports. Static imports are allowed only in test classes.
|
||||
- Comments explain intent or constraints. Document public contracts with Javadoc
|
||||
where their meaning is not clear from the declaration; do not require boilerplate
|
||||
documentation for every accessor.
|
||||
- Block comments use the following layout, subject to Palantir formatting:
|
||||
|
||||
```java
|
||||
/*
|
||||
This is an example of a block comment.
|
||||
It may have more than one line.
|
||||
*/
|
||||
```
|
||||
- Prefer records for immutable data carriers. Classes are allowed when mutation,
|
||||
framework requirements or inheritance make records unsuitable. Preserve API and
|
||||
serialization behavior. Record immutability is shallow: protect mutable
|
||||
components appropriately.
|
||||
- Require `final` for parameters, local variables and fields wherever they can
|
||||
remain assigned once, including loop variables and catch parameters where Java
|
||||
permits it. Field finality must remain compatible with framework injection and
|
||||
lifecycle requirements. Permit reassignment when the algorithm needs it; do not
|
||||
introduce artificial holder objects to avoid reassignment. This rule does not
|
||||
require final classes or methods.
|
||||
- Use explicit types unless the initializer visibly identifies the type. `var` is
|
||||
allowed with `new School(...)` or an explicit cast, but not for method results,
|
||||
literals or other inferred expressions. For example,
|
||||
`final var school = new School(...)` is allowed, while a repository result uses
|
||||
`final School school = repository.find(id)`. Borderline cases require review.
|
||||
- No additional member-ordering or line-width policy beyond Palantir.
|
||||
|
||||
## Metrics
|
||||
|
||||
Targets guide development. Review signals require assessment, not automatic
|
||||
failure. Blocking limits fail verification. Strict inequalities matter: a value
|
||||
exactly at a blocking limit passes.
|
||||
|
||||
| Metric | Target | Review signal | Blocking limit |
|
||||
| --- | ---: | ---: | ---: |
|
||||
| Cyclomatic complexity per method/constructor | ≤ 5 | > 7 | > 10 |
|
||||
| Cognitive complexity per method/constructor | ≤ 10 | > 10 | > 15 |
|
||||
| Method/constructor length, code lines | ≤ 20 | > 30 | > 50 |
|
||||
| Parameters per method | ≤ 3 | > 4 | > 5 |
|
||||
| Parameters per explicitly written constructor | ≤ 4 | > 5 | > 7 |
|
||||
| Injected dependencies per class | ≤ 4 | > 5 | > 7 |
|
||||
| Fan-out per class, unique used types | ≤ 10 | > 15 | Review only |
|
||||
| Own superclass depth, excluding Object | ≤ 1 | > 2 | > 3 |
|
||||
| Control-flow nesting | ≤ 2 | > 3 | > 4 |
|
||||
| Production duplicated lines density | ≤ 1% | > 1% | > 3% |
|
||||
| Class length, code lines | ≤ 200 | > 300 | > 500 |
|
||||
| Declared public methods per class, excluding trivial accessors | ≤ 10 | > 15 | Review only |
|
||||
|
||||
### Measurement definitions
|
||||
|
||||
- Use the pinned PMD algorithms as authoritative for cyclomatic and cognitive
|
||||
complexity. Document their exact configuration, including switch and boolean
|
||||
treatment. Do not accidentally introduce a class-level aggregate complexity gate.
|
||||
- Measure each method, constructor and explicitly written record constructor
|
||||
independently. Lambda bodies contribute to their enclosing executable;
|
||||
methods in nested/local classes are separate executables.
|
||||
- Parameter limits exclude implicit record constructors and generated members.
|
||||
Record component counts remain a design review concern.
|
||||
- Length means physical source lines after Palantir formatting, excluding blank
|
||||
and comment-only lines. Declaration and brace-only lines count; a line containing
|
||||
both code and comments counts. Do not substitute statement counts or NCSS.
|
||||
Measure nested types separately and exclude them from enclosing class length.
|
||||
- Count distinct injected collaborators by resolved type and qualifier. Include
|
||||
constructor, field, setter, inherited and implicit constructor injection.
|
||||
Repeated injection of the same type and qualifier counts once; differently
|
||||
qualified instances of the same type count separately.
|
||||
- Fan-out counts distinct explicitly referenced resolved types, including JDK and
|
||||
framework types. Exclude primitives, the class itself and generated references.
|
||||
- Inheritance depth counts project-owned superclass layers; exclude Object,
|
||||
interfaces and external framework ancestry.
|
||||
- Nesting combines `if`, loops, `switch` and `catch`, with the first structure at
|
||||
depth one. An `else if` chain stays at one level. `else`, `try` and `finally`
|
||||
add no level themselves. Lambdas retain surrounding depth; methods in nested
|
||||
classes start fresh.
|
||||
- Public-method counts include explicitly declared public instance and static
|
||||
methods; exclude constructors, inherited methods and trivial accessors. A
|
||||
trivial accessor only reads or assigns its corresponding field, with no
|
||||
validation, branching or other work.
|
||||
- Duplication limits apply only to production code. Duplication in tests is allowed
|
||||
and has no target, review signal or blocking limit.
|
||||
- Detect production clones with CPD, minimum 100 tokens, without ignoring
|
||||
identifier or literal differences. Density is
|
||||
`100 × distinct duplicated code-line locations / all production code-line locations`.
|
||||
Exclude blank/comment-only lines from numerator and denominator. Count every
|
||||
occurrence, including the first; merge overlapping ranges to count each source
|
||||
line once. This project metric need not equal a future Sonar metric.
|
||||
|
||||
## Enforcement and developer workflow
|
||||
|
||||
- Use explicitly pinned Java-25-compatible Checkstyle and PMD/CPD versions.
|
||||
Retain ArchUnit for architecture checks and add small targeted custom checks
|
||||
where standard rules cannot accurately express the agreed semantics.
|
||||
- Automate every blocking metric and explicit rule where reliable checking is
|
||||
available. Identify rules requiring manual review explicitly; do not claim
|
||||
they are automated. Review signals must appear in reports even when builds pass.
|
||||
- Run standards checks during `mvn verify`; provide documented standalone commands.
|
||||
Ordinary compile/test commands retain the current S8 formatting behavior.
|
||||
- Standards checks report violations without rewriting code. CI passes these
|
||||
checks before image publication. Parser failures or unsupported Java constructs
|
||||
fail with the affected path and actionable diagnostics, rather than being skipped.
|
||||
- Add a root AGENTS.md instruction requiring agents to read CODING_STANDARDS.md
|
||||
before changing backend Java. Project review instructions must explicitly cover
|
||||
manual rules, review signals in changed code and approved waivers, without
|
||||
repeating checks already enforced by tooling.
|
||||
- Keep upstream skill files unchanged. Put project-specific code-review guidance
|
||||
in a companion file referenced by project instructions and used alongside
|
||||
`skills/code-review/SKILL.md`.
|
||||
- Waivers must be explicit, narrowly scoped and carry a recorded reason alongside
|
||||
code or configuration. Agents need maintainer agreement before introducing one.
|
||||
No blanket suppressions, exclusions of difficult files or weakened thresholds
|
||||
merely to make verification pass.
|
||||
|
||||
## Coverage
|
||||
|
||||
- Require at least 80% backend line coverage across handwritten production code
|
||||
for the module as a whole, not separately per class or package. Compare the
|
||||
unrounded percentage against 80%.
|
||||
- Local `mvn verify` must reach 80% using backend unit/integration tests alone.
|
||||
This intentionally tightens the original combined-tests-only requirement.
|
||||
- CI additionally instruments the backend exercised by Playwright, merges that
|
||||
coverage with backend unit/integration coverage and gates the combined result.
|
||||
The Playwright contribution need not separately reach 80%.
|
||||
- Exclude generated code only; do not broadly exclude DTOs, configuration or
|
||||
difficult code. Publish line and branch coverage reports; branch coverage has
|
||||
no agreed blocking percentage.
|
||||
- PIT measures mutation-test effectiveness, not line coverage, and is outside
|
||||
S7's required implementation. Configuring Sonar in the pipeline remains out of
|
||||
scope for S14. FindBugs/SpotBugs is not an additional required check suite.
|
||||
|
||||
## Existing-code migration
|
||||
|
||||
- Bring existing backend production and test Java into compliance, including
|
||||
structural refactoring where necessary.
|
||||
- Migration is complete when all blocking rules pass and all review signals have
|
||||
been assessed, with rationale recorded for retained signals. Reaching every
|
||||
target is not required.
|
||||
- Preserve public APIs, JSON contracts, persistence formats and application
|
||||
behavior. Any necessary contract change requires a separate decision.
|
||||
- Separate enforcement/configuration changes from code refactoring for review.
|
||||
Strengthen tests where migration affects behavior-sensitive code.
|
||||
|
||||
## Acceptance criteria
|
||||
|
||||
- [x] CODING_STANDARDS.md contains all agreed rules and preserves frontend guidance.
|
||||
- [x] Agent and project code-review instructions enforce discovery and review of
|
||||
these standards without modifying upstream skills.
|
||||
- [x] Pinned tools, configurations and targeted checks implement the exact agreed
|
||||
metrics and identify manual-only rules.
|
||||
- [x] Verify and standalone checks report actionable blocking failures and review
|
||||
signals; CI prevents publication after a failure.
|
||||
- [x] Representative violations demonstrate that their checks fail, including
|
||||
relevant threshold boundaries and custom measurement semantics.
|
||||
- [x] Existing handwritten backend production and test code passes all blocking
|
||||
rules; retained review signals and approved waivers are documented.
|
||||
- [x] Local backend tests and combined CI coverage meet the agreed line-coverage
|
||||
gates; line and branch reports are available.
|
||||
- [x] Clean verification and behavior-preservation tests pass after migration.
|
||||
- [x] Evidence records tool versions, commands, scope, exclusions, metric and
|
||||
coverage reports, approved waivers and verification results.
|
||||
|
||||
## Implementation handoff
|
||||
|
||||
This specification records the agreed design. Updating it does not implement
|
||||
checks, change agent instructions, refactor application code or establish current
|
||||
coverage. Those are implementation work, with evidence required above.
|
||||
|
||||
## Implementation evidence
|
||||
|
||||
Implementation and verification are recorded in `specs/S7-validation.md`; retained
|
||||
review signals and the sole approved waiver are recorded in
|
||||
`specs/S7-review-signals.txt` and `tooling/standards/waivers.tsv`.
|
||||
|
||||
The maintainer approved GroupDetails-based Java service signatures and the exact
|
||||
eight-parameter Group constructor waiver in the implementation conversation.
|
||||
REST/JSON contracts remain unchanged. Clean verify and browser/combined coverage
|
||||
checks pass. The implementation is ready for project review.
|
||||
|
||||
|
||||
Affected repositories: `agiledancers`.
|
||||
203
specs/implemented/S8_palentir-formatting-be
Normal file
203
specs/implemented/S8_palentir-formatting-be
Normal file
@@ -0,0 +1,203 @@
|
||||
# S8 — Palantir formatting for Java
|
||||
|
||||
Status: IMPLEMENTED
|
||||
|
||||
Agreed after the grill-me review; shared understanding confirmed.
|
||||
|
||||
## User story
|
||||
|
||||
As a developer, I want maintained Java code formatted using Palantir Java Format
|
||||
through the Maven workflow, so that local development and CI use consistent,
|
||||
reproducible formatting without unnecessary build overhead.
|
||||
|
||||
## Scope
|
||||
|
||||
### In scope
|
||||
|
||||
- Backend Java production code and Java tests.
|
||||
- Maintained Java CI/source-launcher helpers under `ci/`, despite those files
|
||||
being outside ordinary Maven source roots.
|
||||
- Integration with local Maven builds, CI checking and standalone format/check
|
||||
commands.
|
||||
- A separate initial formatting commit, performance measurements and README
|
||||
instructions.
|
||||
|
||||
### Out of scope
|
||||
|
||||
- Generated code and build output.
|
||||
- Frontend formatting, which remains under Prettier.
|
||||
- Additional coding conventions, naming rules, structural checks or refactorings.
|
||||
Those belong in S7.
|
||||
|
||||
## Formatter and integration
|
||||
|
||||
- Use the **actual Palantir Java Format engine** and its Palantir style.
|
||||
- OpenRewrite is the preferred integration route. S8 includes the custom
|
||||
Palantir adapter/recipe and bootstrap required to make that route work.
|
||||
- OpenRewrite's own `AutoFormat` is not an equivalent replacement for Palantir
|
||||
and must not be substituted silently.
|
||||
- Spotless is not the agreed default: the maintainer has experienced unacceptable
|
||||
slowness with it. Do not choose it merely because a native integration exists.
|
||||
- Pin the formatter, plugin and adapter dependencies to explicit versions in
|
||||
Maven configuration. Local development and CI use the same pinned engine.
|
||||
- Formatter/integration updates are reviewed through PRs and include any resulting
|
||||
formatting changes. Do not implicitly resolve the newest formatter at build time.
|
||||
- Include Palantir's import ordering and unused-import removal. Do not add
|
||||
separate import policies or unrelated code transformations.
|
||||
- Leave optional extra Javadoc reformatting disabled for the initial adoption.
|
||||
|
||||
## Maven behavior
|
||||
|
||||
### Local builds
|
||||
|
||||
Local builds apply formatting before compilation, so the compiled and tested
|
||||
sources are the formatted sources. Early lifecycle integration means ordinary
|
||||
`mvn compile`, `mvn test`, `mvn verify` and `mvn install` may format maintained
|
||||
Java files.
|
||||
|
||||
Binding only to `install` does not satisfy this specification: the existing CI
|
||||
verification uses `mvn clean verify` and would not reach that phase.
|
||||
|
||||
Provide standalone commands to:
|
||||
|
||||
- Apply formatting without performing the complete application build.
|
||||
- Check formatting without modifying maintained sources or performing the complete
|
||||
application build.
|
||||
|
||||
The concrete commands/profile names are implementation work and must be documented.
|
||||
|
||||
### CI
|
||||
|
||||
- CI runs the check-only mode before compilation and fails if formatting differs
|
||||
from the committed source.
|
||||
- CI must not repair or rewrite maintained Java source files automatically.
|
||||
- Use the same pinned Palantir engine, configuration and file scope locally and
|
||||
in CI; only apply versus check behavior differs.
|
||||
- Integrate the checking invocation into the existing Java-based CI orchestration.
|
||||
- Show actionable diagnostics identifying the files that need formatting and how
|
||||
to apply the formatter locally.
|
||||
- A formatting failure prevents successful verification and image publication.
|
||||
Demonstrate that the check leaves maintained source files unchanged on failure.
|
||||
|
||||
## Clean-checkout bootstrap
|
||||
|
||||
Normal Maven commands from the repository root must work from a clean checkout
|
||||
without first requiring a developer to compile or install a custom recipe artifact
|
||||
by hand.
|
||||
|
||||
The custom recipe/adapter must be available before it is needed to format the
|
||||
application sources. Placing it in ordinary backend source code and assuming that
|
||||
it has already been compiled is not a valid bootstrap solution.
|
||||
|
||||
Prove bootstrap behavior with no previously installed project-specific recipe
|
||||
artifact. Normal dependency resolution is allowed; any extra tooling module or
|
||||
bootstrap must be included in the implementation and documentation.
|
||||
|
||||
## Correctness and Java 25
|
||||
|
||||
- Demonstrate support for every Java construct actually used in the maintained
|
||||
backend, tests and CI helpers on the project's JDK 25.
|
||||
- Running the formatter on JDK 25 is not, by itself, proof that its parser supports
|
||||
every possible Java 25 construct. Record relevant limitations of the chosen
|
||||
pinned version.
|
||||
- An unprocessable file or formatter error fails the operation/build with its
|
||||
path and a concrete cause. Do not silently skip it or exclude it merely to
|
||||
obtain a successful build or faster measurement.
|
||||
- The adapter must preserve source paths and encoding and avoid corrupting files.
|
||||
- Formatting is deterministic and idempotent: applying it again produces no
|
||||
further source differences. Check-only and apply mode agree on the result.
|
||||
- Application behavior remains unchanged; builds and tests must pass after the
|
||||
initial formatting and subsequent formatter changes.
|
||||
|
||||
## Initial adoption and commit separation
|
||||
|
||||
Apply the chosen formatting to all existing maintained Java files in scope.
|
||||
Record this initial mass formatting in a separate **formatting-only commit**,
|
||||
without functional changes. Keep integration/configuration changes separate so
|
||||
reviewers can distinguish tooling changes from the mechanical source rewrite.
|
||||
|
||||
Native import ordering/removal is part of that formatting commit. Do not combine
|
||||
it with unrelated cleanup or refactoring.
|
||||
|
||||
## Performance requirements
|
||||
|
||||
The integration must be measured rather than selected on an unverified claim that
|
||||
one wrapper is faster than another.
|
||||
|
||||
- A repeated ordinary build with no Java-source changes may incur at most
|
||||
**three seconds of additional formatting-related overhead**.
|
||||
- Include the required integration/recipe/bootstrap overhead in that comparison;
|
||||
do not report only time spent inside the Palantir formatting function.
|
||||
- Compare otherwise equivalent builds with and without the formatting integration
|
||||
under the same environment/cache conditions.
|
||||
- Also measure a build after changing a maintained Java file and a `clean verify`
|
||||
run. Record these timings; the agreed three-second threshold specifically
|
||||
applies to the repeated unchanged-build case.
|
||||
- Report one-time dependency downloads separately, rather than disguising ongoing
|
||||
overhead as first-time setup or counting downloads as formatter execution.
|
||||
- Record the machine, JDK/Maven/tool versions, commands, file scope, cache state
|
||||
and results with the implementation evidence.
|
||||
|
||||
The time threshold is an acceptance criterion, not a hard interrupt that kills a
|
||||
formatter while it is writing source files. If the selected integration cannot
|
||||
meet the threshold, report the measurements and obtain agreement before choosing
|
||||
an alternative integration or relaxing the bound. Do not silently skip formatting,
|
||||
switch engines, choose Spotless or weaken the criterion.
|
||||
|
||||
## README and editor integration
|
||||
|
||||
Explain in the root `README.md`:
|
||||
|
||||
- The formatter, pinned versions/configuration and maintained file scope.
|
||||
- The standalone apply and check commands.
|
||||
- Which local Maven lifecycle commands can rewrite files and when that occurs.
|
||||
- The CI check-only invocation and how to reproduce and resolve a failure locally.
|
||||
- Clean-checkout bootstrap behavior and any included tooling artifact/module.
|
||||
- Available supported IDE integration and how to keep its result consistent with
|
||||
the project's pinned formatter.
|
||||
- The performance evidence and any relevant Java 25 syntax limitations.
|
||||
|
||||
Maven is the authoritative formatting path regardless of editor. Do not require
|
||||
format-on-save or an IDE plugin. An IDE integration must not redefine the agreed
|
||||
style or silently take precedence over the Maven result.
|
||||
|
||||
## Acceptance criteria
|
||||
|
||||
- [x] The actual Palantir engine formats all maintained backend Java sources,
|
||||
Java tests and `ci/*.java`; generated code is excluded.
|
||||
- [x] OpenRewrite integration, custom adapter/recipe and bootstrap are implemented
|
||||
and reproducible from a clean checkout without manual recipe installation.
|
||||
- [x] Plugin, formatter and adapter dependencies are pinned, with matching local
|
||||
and CI configuration.
|
||||
- [x] Local Maven builds apply formatting before compilation; `compile`, `test`,
|
||||
`verify` and `install` reach the intended integration.
|
||||
- [x] Standalone apply and check commands work without the full application build.
|
||||
- [x] CI checks only, leaves maintained sources unchanged, reports formatting
|
||||
differences and fails before image publication.
|
||||
- [x] Import ordering and unused-import removal follow Palantir; optional extra
|
||||
Javadoc reformatting remains disabled and no unrelated refactoring is added.
|
||||
- [x] All currently used Java 25 syntax is handled, or causes an explicit failure
|
||||
requiring resolution rather than silent exclusion.
|
||||
- [x] Apply/check results agree and a second apply produces no differences.
|
||||
- [x] Initial formatting is isolated in a formatting-only commit; application
|
||||
builds and tests remain green.
|
||||
- [x] Equivalent repeated unchanged-build measurements demonstrate at most three
|
||||
seconds of additional integration overhead. Changed-file and clean-build
|
||||
measurements and one-time downloads are reported separately.
|
||||
- [x] Failure to meet the performance bound is reported before changing the route
|
||||
or bound; a writing formatter is not killed to force compliance.
|
||||
- [x] README instructions cover local and CI commands, bootstrap, optional IDE
|
||||
use, authoritative Maven formatting and verification evidence.
|
||||
|
||||
## Implementation handoff
|
||||
|
||||
This specification records agreed behavior. It does not install a formatter,
|
||||
create an adapter, change Maven/CI behavior or reformat source files. Recipe loading,
|
||||
Java 25 compatibility and performance must be demonstrated during implementation;
|
||||
there is no pre-existing project benchmark establishing the preferred route's
|
||||
performance.
|
||||
|
||||
Implementation and measured acceptance evidence: [S8-formatting-evidence.md](http://192.168.2.28:3000/wanjakrah/agiledancers/src/branch/feature/S19_multi-project/docs/validation/S8-formatting-evidence.md).
|
||||
|
||||
|
||||
Affected repositories: `agiledancers`.
|
||||
166
specs/implemented/S9_spread-dancegroups-via-ortools-setup
Normal file
166
specs/implemented/S9_spread-dancegroups-via-ortools-setup
Normal file
@@ -0,0 +1,166 @@
|
||||
# S9 — Schedule dance groups across show dayparts with OR-Tools
|
||||
|
||||
Status: IMPLEMENTED
|
||||
|
||||
Agreed after the grill-me review; shared understanding confirmed.
|
||||
|
||||
## User story
|
||||
|
||||
As a dance-school maintainer, I want to assign my school's dance groups to a
|
||||
show's dated dayparts, using configurable appearance counts per group type,
|
||||
so that appearances are spread evenly across the show.
|
||||
|
||||
## Show configuration
|
||||
|
||||
- A show can have one to six dayparts across multiple dates. Each daypart has a
|
||||
date and a type: MORNING, AFTERNOON or EVENING. A date/type combination must be
|
||||
unique within a show. For example, Friday afternoon, Saturday afternoon and
|
||||
Saturday evening are three distinct dayparts.
|
||||
- An unscheduled show may have no dayparts while being configured.
|
||||
- Daypart dates are the source of truth. Remove the separate editable show date.
|
||||
Display the range from the earliest to the latest daypart date, or
|
||||
"No dates configured" when there are none.
|
||||
- Each show stores an editable appearance count for every dance-group type,
|
||||
including types with no current groups. Remove the backend
|
||||
`DanceGroupType.dayPartsRequired` property.
|
||||
- Initialize counts when creating the show using the following defaults, where
|
||||
N is the configured number of dayparts:
|
||||
|
||||
| Type | Default appearances |
|
||||
| --- | --- |
|
||||
| PRE_SCHOOLER | 1 |
|
||||
| SHOW_CASE | N |
|
||||
| PRE_EDUCATION | N |
|
||||
| All remaining types | min(2, N) |
|
||||
|
||||
- PRE_SCHOOLER's count is editable; one is a default, not a fixed exception.
|
||||
- Both frontend and backend enforce integer counts greater than zero and no
|
||||
greater than N for a configured show. With one daypart, all fields display one
|
||||
and are disabled in the frontend.
|
||||
- A show without dayparts remains unscheduled; usable counts must be initialized
|
||||
when its initial daypart configuration becomes available.
|
||||
- Subsequent daypart edits preserve the saved counts rather than reapplying
|
||||
defaults. Block saving if a count exceeds the new number of dayparts until
|
||||
the user corrects it. Adding a daypart does not automatically increase counts.
|
||||
|
||||
## Scheduling rules and objective
|
||||
|
||||
- Use Google OR-Tools in the backend.
|
||||
- Include every current dance group belonging to the show's school.
|
||||
- Each group must appear in exactly the number of distinct dayparts configured
|
||||
for its type. A group cannot appear twice within one daypart.
|
||||
- Among assignments satisfying those requirements, minimize the difference
|
||||
between the largest and smallest number of group appearances per daypart.
|
||||
Count every configured daypart, including an empty one.
|
||||
- Assign groups to dayparts only. Do not calculate performance order or timing.
|
||||
- Require at least one school group and one configured daypart. Disable the
|
||||
scheduling action with an explanation when either is missing, and enforce
|
||||
the same requirements in the backend.
|
||||
|
||||
## Scheduling action and result handling
|
||||
|
||||
- Provide an explicit "Schedule groups" action clearly indicating that it
|
||||
replaces the current assignments. A separate preview/accept workflow is
|
||||
outside this specification.
|
||||
- Run scheduling synchronously, with a solver time limit of 30 minutes.
|
||||
For S9, the frontend may remain blocked until the request returns; configure
|
||||
the request path to accommodate the agreed duration.
|
||||
- If a valid result is found, save it as a complete replacement of the existing
|
||||
assignments. This includes a valid result whose optimality has not been proven
|
||||
when the time limit is reached.
|
||||
- Distinguish "optimal balance" from "valid result; optimal balance not proven"
|
||||
in the result presented to the user.
|
||||
- If validation fails, the problem is infeasible, the solver fails, or the limit
|
||||
is reached without a valid result, explain the outcome and preserve existing
|
||||
assignments. Never silently reduce required appearances.
|
||||
- Disable the scheduling action while a run is pending. The backend must reject
|
||||
another concurrent run for the same show.
|
||||
- Before saving, verify that scheduling inputs have not changed during the run.
|
||||
If they changed, reject the stale result, preserve existing assignments and
|
||||
explain that the user must run scheduling again.
|
||||
|
||||
## Changes affecting existing schedules
|
||||
|
||||
- Before accepting a potentially invalidating edit, warn that an existing show
|
||||
schedule may become invalid, name the affected shows and allow cancellation.
|
||||
- Cover adding/deleting school groups, changing a group's type, changing show
|
||||
dayparts and changing appearance counts when affected shows have assignments.
|
||||
Name-only edits do not require this warning.
|
||||
- After accepting the edit, do not automatically reschedule. Identify schedules
|
||||
whose assignments no longer meet the appearance requirements and offer the
|
||||
explicit scheduling action again.
|
||||
- Newly added groups use their type's saved count on the next scheduling run.
|
||||
|
||||
## JSON import/export
|
||||
|
||||
- Preserve dated dayparts, group assignments and every per-type appearance
|
||||
setting through JSON export/import.
|
||||
- Update the format version and validation for the new structure, including
|
||||
allowing the same daypart type on different dates.
|
||||
- No legacy export compatibility or migration is required: the application is
|
||||
still greenfield and no exports have been made.
|
||||
|
||||
## Optional repeatability
|
||||
|
||||
Identical inputs producing identical assignments is a nice-to-have for
|
||||
testability, not a mandatory scheduling requirement. Spend at most three
|
||||
minutes investigating how to achieve it. Implement it only if it requires at
|
||||
most ten additional code statements; otherwise omit it. Changed inputs may
|
||||
produce different assignments regardless.
|
||||
|
||||
## Out of scope and follow-up specifications
|
||||
|
||||
- Group exclusions: S10_allow-group-exclusion-for-show.
|
||||
- Season context: S11_add-season-context-go-groups-and-shows.
|
||||
- Asynchronous scheduling feedback: S12_support-async-feedback-for-scheduling.
|
||||
- Scheduling on another PC: S13_create-runner-to-allow-scheduling-on-different-pc.
|
||||
- Availability restrictions, pinned assignments, capacity limits, shared-dancer
|
||||
constraints, duration/audience balancing and performance ordering.
|
||||
|
||||
S10–S13 are intentionally empty placeholders and are to be refined separately.
|
||||
|
||||
## Acceptance criteria
|
||||
|
||||
- [x] Configure up to six dated dayparts, reject duplicate date/type combinations
|
||||
and derive the displayed show date range from them.
|
||||
- [x] Persist editable per-type counts with the agreed defaults, remove the
|
||||
backend type-level property and validate counts in frontend and backend.
|
||||
- [x] With one daypart, every count is one and frontend fields are disabled.
|
||||
- [x] Daypart edits preserve configured counts and require correction of counts
|
||||
that exceed the new number of dayparts.
|
||||
- [x] OR-Tools assigns every school group to exactly its type's required number
|
||||
of distinct dayparts and minimizes the busiest/quietest appearance gap.
|
||||
- [x] Scheduling requires groups and dayparts and replaces assignments only after
|
||||
a successful, current result.
|
||||
- [x] The synchronous request supports a 30-minute solver limit, accepts valid
|
||||
unproven results and communicates whether optimality was proven.
|
||||
- [x] Failed, infeasible, stale and no-result runs preserve existing assignments
|
||||
and explain why no replacement was saved.
|
||||
- [x] Duplicate concurrent runs for a show are prevented in frontend and backend.
|
||||
- [x] Potentially invalidating edits warn beforehand, identify affected shows,
|
||||
permit cancellation and expose invalid schedules afterward without
|
||||
automatically rescheduling.
|
||||
- [x] New-format JSON round-trips dates, assignments and all type settings;
|
||||
legacy import support is not required.
|
||||
- [x] Any repeatability work respects both the three-minute investigation limit
|
||||
and the ten-additional-statement implementation limit.
|
||||
|
||||
## Implementation handoff
|
||||
|
||||
This specification records the agreed behavior implemented on the current branch.
|
||||
The current application uses in-memory storage with JSON import/export for
|
||||
transfer. S9 adds the scheduling model, frontend controls, backend operation and
|
||||
JSON changes within that existing persistence approach.
|
||||
|
||||
## Implementation validation
|
||||
|
||||
- Backend: 29 tests, including real OR-Tools balancing, input validation, JSON
|
||||
round-trips, concurrent scheduling, stale input rejection and failure preservation.
|
||||
- Frontend: 20 tests covering count validation, disabled single-daypart fields, edit cancellation,
|
||||
API timeout contract, production build and lint checks.
|
||||
- Playwright: real REST workflow for dated dayparts, scheduling and cancellation.
|
||||
- Repeatability uses one solver-parameter statement (single worker, fixed seed);
|
||||
no extended investigation was needed.
|
||||
|
||||
|
||||
Affected repositories: `agiledancers`.
|
||||
167
specs/in_progress/S19_multi-project
Normal file
167
specs/in_progress/S19_multi-project
Normal file
@@ -0,0 +1,167 @@
|
||||
As developer
|
||||
I want to separate landscape documentation and reusable engineering resources from Agile Dancers
|
||||
so that I adhere to ADR1 and can start and maintain multiple projects with a complete, versioned engineering setup.
|
||||
|
||||
Status: IN_PROGRESS
|
||||
|
||||
Architecture: ADR1, Application size (`adr/approved/ADR1_application-size.md` before migration).
|
||||
|
||||
Affected repositories:
|
||||
|
||||
- `agiledancers` (existing application repository)
|
||||
- `landscape` (new repository)
|
||||
- `engineering` (new repository)
|
||||
|
||||
## Intent
|
||||
|
||||
Create `landscape` and `engineering` on the existing Gitea server, under the same
|
||||
owner as `agiledancers`. Check them out to `~/Projecten/git/landscape` and
|
||||
`~/Projecten/git/engineering`.
|
||||
|
||||
Keep Agile Dancers working throughout the migration. Fully generalize the
|
||||
engineering setup so another project can start with a ready-to-use pipeline
|
||||
recipe. Moving application-specific helpers unchanged into another repository
|
||||
does not satisfy this specification.
|
||||
|
||||
## Repository ownership
|
||||
|
||||
### Landscape
|
||||
|
||||
Move ADRs and specifications, including this specification, to `landscape`.
|
||||
Maintain the capability and system map there, recording current boundaries and
|
||||
leaving future business-system extraction to follow-up specifications. Each
|
||||
specification identifies the repositories it affects.
|
||||
|
||||
Landscape also contains instructions for starting projects that use this setup,
|
||||
including repository creation, use of the engineering project generator,
|
||||
configuration, secrets setup, and engineering upgrades. Link to engineering's
|
||||
technical usage instructions rather than maintaining duplicate instructions.
|
||||
|
||||
### Engineering
|
||||
|
||||
Move reusable skills, general engineering documentation, coding standards,
|
||||
tooling, and generalized pipeline and deployment mechanisms to `engineering`.
|
||||
Include templates and a project generator for new consumers.
|
||||
|
||||
Generalize the existing CI, deployment, formatting, standards, and coverage
|
||||
helpers as needed. This includes helpers such as `ci/Pipeline.java`; substantial
|
||||
generalization is part of S19 rather than deferred merely because it requires
|
||||
more than a small configuration change.
|
||||
|
||||
Keep upstream skill files unchanged. Preserve their revision records, licenses,
|
||||
and attribution, including the files currently recorded in `skills/upstream.json`.
|
||||
|
||||
### Application repositories
|
||||
|
||||
Keep implementation code, executable tests, fixtures, historical application
|
||||
validation reports, and implementation and operational instructions with their
|
||||
application. Keep project-specific configuration and adapters here, including
|
||||
Compose configuration, deployment targets, secret references, and existing
|
||||
maintainer-approved standards waivers. Do not copy application waivers into
|
||||
defaults for other projects. Do not commit secret values.
|
||||
|
||||
Classify every existing resource in the ADR, specification, CI, deployment,
|
||||
documentation, skills, and tooling folders. Record its destination and the reason
|
||||
it moves or stays. For mixed resources, separate the general mechanism from
|
||||
application configuration rather than assigning the whole folder one destination.
|
||||
|
||||
## Versioned consumption and generation
|
||||
|
||||
Release engineering as one package using semantic version tags such as `v1.0.0`.
|
||||
Published tags are immutable; breaking changes require a new major version.
|
||||
Consumers adopt upgrades explicitly and record both the selected tag and its
|
||||
resolved commit. Reject a fetch when the tag no longer resolves to that commit.
|
||||
|
||||
Copy the selected engineering resources into a committed `generated/` folder in
|
||||
each consuming project. Record their source and version. Treat these files as
|
||||
generated output: make general changes in engineering and regenerate the local
|
||||
copy. Regeneration replaces generated content, including removal of obsolete
|
||||
generated files, without overwriting project-owned files outside that folder.
|
||||
|
||||
Provide a small project-local bootstrap script and version configuration outside
|
||||
`generated/`. Add a Maven profile that invokes the script to regenerate from the
|
||||
selected engineering version. The profile must work when `generated/` is absent;
|
||||
it must not require generated tooling to bootstrap itself.
|
||||
|
||||
Ordinary local builds use the committed resources without downloading or
|
||||
regenerating them each time. Access to engineering can be assumed for explicit
|
||||
regeneration and CI. No Nexus or other artifact repository is required.
|
||||
|
||||
CI regenerates from the recorded tag and commit and fails if the resulting
|
||||
generated files differ from the committed files, including added or removed
|
||||
files. CI does not select a newer engineering release automatically.
|
||||
|
||||
Keep Maven verification, standalone Docker builds, CI, and agent instructions
|
||||
working with these paths. A fresh application clone must not depend on sibling
|
||||
repository checkouts or globally installed project skills.
|
||||
|
||||
## General pipeline recipe and project generator
|
||||
|
||||
Support Gitea Actions, Maven/Java, npm, and Docker Compose. Projects can select a
|
||||
backend, a frontend, or both. Other build systems and deployment platforms are
|
||||
outside this specification.
|
||||
|
||||
Make project names, module paths, image names, deployment servers and paths,
|
||||
and healthchecks configurable. Provide shared build, test, image-build,
|
||||
deployment, and rollback mechanisms. Application secrets remain configured by
|
||||
the consuming project; engineering supplies the mechanism and instructions.
|
||||
|
||||
Provide a command that creates a local project skeleton from templates using a
|
||||
project name and the selected components. Include pipeline workflows, project
|
||||
configuration, bootstrap script, engineering version configuration, and agent
|
||||
instructions. Repository creation and secrets configuration are documented
|
||||
setup steps rather than actions performed by this generator.
|
||||
|
||||
The generator creates project-owned files such as `pom.xml`, workflows, and
|
||||
Compose configuration once. Subsequent engineering upgrades automatically
|
||||
replace only `generated/`. Supply upgrade instructions when project-owned files
|
||||
also require changes. Keep these project-owned files thin by delegating shared
|
||||
behavior to generated engineering resources.
|
||||
|
||||
Include a small example project in engineering that consumes the same recipe
|
||||
and proves it works without hidden Agile Dancers assumptions. Validate its
|
||||
deployment and rollback in an isolated test environment.
|
||||
|
||||
## Documentation and traceability
|
||||
|
||||
Start the new repositories with attributed snapshots. Record the source
|
||||
repository and source commit; retain the existing history in Agile Dancers.
|
||||
Extracting Git history into the new repositories is not required.
|
||||
|
||||
Update README, AGENTS, and affected links after moving files. Explain how agents
|
||||
and maintainers locate landscape guidance, use the pinned engineering resources,
|
||||
regenerate them, and adopt upgrades. Landscape guidance may be referenced at its
|
||||
current revision; executable engineering resources remain pinned. Use fixed
|
||||
commits where historical evidence needs a stable reference.
|
||||
|
||||
Repair links between moved specifications and application validation evidence.
|
||||
Each application's README continues to describe its implementation and operation.
|
||||
|
||||
## Migration and acceptance criteria
|
||||
|
||||
Migrate incrementally, keeping the application working after each extraction.
|
||||
Complete the following before considering S19 implemented:
|
||||
|
||||
1. Both new repositories exist in Gitea and at the agreed local checkout paths.
|
||||
2. The resource classification is complete, destinations follow ADR1, and moved
|
||||
files retain source attribution and applicable licenses.
|
||||
3. Engineering has a tagged release, a documented generator and upgrade process,
|
||||
and fully generalized mechanisms for the supported stack.
|
||||
4. Agile Dancers consumes the recorded engineering tag and commit through
|
||||
committed generated resources. Regeneration works from a clean checkout and
|
||||
with `generated/` absent. CI detects generated-file drift and rejects a moved
|
||||
tag without silently upgrading.
|
||||
5. A clean Agile Dancers checkout passes the required build and test checks and
|
||||
builds its Docker image without sibling checkouts. Its Gitea build workflow
|
||||
succeeds with the new resource layout.
|
||||
6. Agile Dancers deployment and rollback configuration is validated. Record any
|
||||
behavior that cannot be verified without a production deployment as an
|
||||
explicit validation limit.
|
||||
7. The example project is generated from the recipe, builds and tests from a
|
||||
clean checkout, and demonstrates deployment and rollback in an isolated
|
||||
environment.
|
||||
8. README, AGENTS, landscape onboarding instructions, and affected links explain
|
||||
and correctly reference the resulting setup.
|
||||
|
||||
Production deployment is a separate action. Business capability extraction,
|
||||
runtime system boundaries, and migration of application data are outside S19.
|
||||
258
specs/refined/S5_renovate-bot-in-container
Normal file
258
specs/refined/S5_renovate-bot-in-container
Normal file
@@ -0,0 +1,258 @@
|
||||
# S5 — Renovate bot in a container
|
||||
|
||||
Status: REFINED
|
||||
|
||||
Agreed after the grill-me review; shared understanding confirmed.
|
||||
|
||||
## User story
|
||||
|
||||
As a developer, I want a containerized Renovate bot to check the repositories on
|
||||
our Gitea server and propose dependency updates through pull requests, so that
|
||||
frontend, backend and build infrastructure dependencies remain maintainable and
|
||||
we reduce risks from outdated versions.
|
||||
|
||||
I want external release age and project compatibility to constrain those
|
||||
proposals. I retain control over merging and can upgrade dependencies manually
|
||||
when I deliberately choose to act outside the bot's waiting period.
|
||||
|
||||
## Environment and scope
|
||||
|
||||
- Gitea and its container registry run on the existing Synology. Renovate runs in
|
||||
a container on that same Synology; no additional hardware is required.
|
||||
- The established Synology target platform is `linux/amd64`.
|
||||
- Discover all repositories on this Gitea instance for which the dedicated bot
|
||||
account has the necessary access. Support explicit repository exclusions.
|
||||
- Before dependency PRs are proposed for a newly discovered repository, create an
|
||||
onboarding/configuration PR. A maintainer must approve and merge that
|
||||
configuration first.
|
||||
- This project contains a `renovate.json` with its agreed compatibility and update
|
||||
boundaries. Other onboarded repositories have their own reviewed configuration.
|
||||
- Use a dedicated bot account/token with the access required for repository
|
||||
discovery, branches, PRs, dashboards and dependency metadata lookup. Keep
|
||||
credential values outside Git and logs.
|
||||
|
||||
### Dependency surfaces
|
||||
|
||||
Cover supported maintained dependency declarations, including:
|
||||
|
||||
- Frontend dependencies and development dependencies, compilers and test tools.
|
||||
- Backend dependencies, Maven parents/BOMs, plugins and version properties.
|
||||
- Docker base images and maintained container-image references.
|
||||
- Pinned workflow actions, including version/digest references.
|
||||
- The Renovate container's own version declaration.
|
||||
- Related lockfile changes and separate lockfile maintenance.
|
||||
|
||||
Detection must include relevant maintained references outside ordinary manifests,
|
||||
for example the Playwright image reference in the Java CI helper. Where related
|
||||
references must match, update and validate them together. The Playwright package
|
||||
and browser image must stay aligned.
|
||||
|
||||
One explicit manual boundary remains: the runner binary download version and its
|
||||
binary SHA-256 checksum in the CI setup helper are maintained manually. Document
|
||||
this boundary. Do not generate a partial runner update, leave an obsolete
|
||||
checksum, or confuse a Git commit SHA with the binary's SHA-256.
|
||||
|
||||
Unsupported dependency references or missing required metadata must be visible as
|
||||
limitations/blockers, rather than silently counted as successfully managed.
|
||||
|
||||
## Schedule and execution
|
||||
|
||||
- Run daily at **06:00 in `Europe/Amsterdam`**. The schedule/timezone are
|
||||
configurable and the default is recorded in the deployment configuration.
|
||||
- Provide the actual scheduler/container setup on the Synology; adding an image
|
||||
declaration alone does not make the periodic execution operational.
|
||||
- The Synology can perform dependency checks while the development mini-PC is
|
||||
off. Project CI jobs still depend on their existing runner availability.
|
||||
- The daily run can discover candidates, maintain eligible PRs and propose new
|
||||
eligible updates within the agreed limits. It does not merge updates.
|
||||
|
||||
## Seven-day release-age policy
|
||||
|
||||
### Universal bot policy
|
||||
|
||||
- A release must be at least **seven days old** before Renovate proposes that
|
||||
version in a dependency PR.
|
||||
- Apply this to all bot-proposed dependency updates, including internal libraries,
|
||||
security updates, infrastructure dependencies and the bot's own image update.
|
||||
There is no internal-library or security-update exception.
|
||||
- Apply the same check when an existing PR is updated to a newer version. An
|
||||
existing eligible PR must not gain an ineligible new version through refresh.
|
||||
- Missing or unreliable release timestamps block the affected proposal until its
|
||||
age is demonstrable. Do not treat missing metadata as proof of sufficient age.
|
||||
- Show the concrete blocker in the repository dashboard, with useful diagnostics.
|
||||
A dependent/coherent update group cannot be partially proposed in an invalid
|
||||
combination to work around an age blocker.
|
||||
- Enforce the policy centrally across onboarded repositories. Repository-local
|
||||
configuration, security-update defaults or bot retry/approval mechanisms must
|
||||
not silently relax the waiting period or timestamp requirement.
|
||||
- A maintainer may choose to upgrade earlier **manually**, outside Renovate. That
|
||||
does not authorize Renovate to bypass its policy.
|
||||
|
||||
### Lockfiles and transitives
|
||||
|
||||
The waiting period also applies to newly introduced or changed transitive
|
||||
versions in bot-generated lockfile changes. Determine those changes relative to
|
||||
the repository base revision used by the proposal.
|
||||
|
||||
- Validate the age of those versions before the PR is created or updated.
|
||||
- Unknown ages block the affected proposal, just as they do for direct updates.
|
||||
- Existing unchanged versions in the base revision are not newly introduced by
|
||||
the bot; the policy is not a requirement to rewrite all historical lock entries.
|
||||
- Additional validation is part of S5 where Renovate's native behavior cannot
|
||||
establish this guarantee. Do not assume a package-manager cutoff covers every
|
||||
fallback path.
|
||||
- A failing validator must actually prevent PR creation/update. A command that
|
||||
fails but only adds an artifact error or failed status to an already-created
|
||||
ineligible PR does not satisfy this requirement.
|
||||
|
||||
### Metadata limitations
|
||||
|
||||
Not every datasource/registry supplies usable release timestamps. This includes
|
||||
some container-image sources. Such updates remain blocked and visible unless
|
||||
reliable metadata support is implemented and validated; manual maintenance is
|
||||
possible outside the bot.
|
||||
|
||||
For example, the npm release timestamp of Playwright is not proof of the release
|
||||
age of its separately published container image. Both references must satisfy
|
||||
applicable policy before their coordinated bot proposal is offered.
|
||||
|
||||
## Compatibility and upgrade boundaries
|
||||
|
||||
### Project-owned boundaries
|
||||
|
||||
- The official Angular compatibility table is the reference for Angular's Node.js,
|
||||
TypeScript and RxJS compatibility: <https://angular.dev/reference/versions>.
|
||||
- Project maintainers encode and maintain the applicable ranges in
|
||||
`renovate.json`, including supported Node majors and TypeScript minor ranges.
|
||||
- Renovate must stay within those explicit ranges and must not independently
|
||||
widen the policy to make a proposed version eligible.
|
||||
- Boundaries must reflect the actual installed framework/tooling metadata where
|
||||
relevant. Remaining in the same dependency major is not sufficient if Angular
|
||||
requires a narrower range.
|
||||
- Node.js, TypeScript and RxJS updates, including major updates, may be proposed
|
||||
when the explicit project boundaries allow them and they remain compatible with
|
||||
the project's Angular version.
|
||||
|
||||
### Angular upgrades
|
||||
|
||||
- Angular major upgrades are performed manually through a separate specification.
|
||||
- Libraries/tooling whose major numbering follows Angular are upgraded to a new
|
||||
major with Angular, also through that manual specification.
|
||||
- Renovate proposes only minor and patch updates for Angular and that aligned
|
||||
family, maintaining a coherent compatible combination.
|
||||
- Runtime/compiler dependencies that require matching versions stay aligned.
|
||||
Do not assume unrelated Angular tooling repositories must all have identical
|
||||
patch numbers merely because their majors align.
|
||||
- Group related changes where necessary to preserve compatibility. TypeScript and
|
||||
RxJS proposals still obey their own explicit allowed ranges.
|
||||
|
||||
### Declared versions versus installed software
|
||||
|
||||
Maintain coherent repository declarations where a dependency appears in multiple
|
||||
places, such as Node requirements in manifests, version files, Docker definitions
|
||||
and setup checks. A bot PR does not install a new Node version on the mini-PC or
|
||||
replace a running container. Those are documented manual management actions.
|
||||
|
||||
## Branches, PRs and limits
|
||||
|
||||
- Use the branch prefix `renovate/`.
|
||||
- Use `renovate/major/<dependency-or-group>` for eligible major updates.
|
||||
- Use `renovate/minor-patch/<dependency-or-group>` for eligible minor/patch updates.
|
||||
- Each independent dependency has its own update PR. Related packages from one
|
||||
upstream project may be grouped to maintain a coherent update.
|
||||
- Keep major-update proposals separate from minor/patch proposals. Necessary
|
||||
companion changes belong with the coherent upgrade they support; unrelated
|
||||
smaller updates are not mixed into a major PR.
|
||||
- Maintain at most **five open dependency PRs per repository**, including the
|
||||
separate lockfile-maintenance PR when one exists.
|
||||
- Queue additional eligible updates for a later daily round after slots become
|
||||
available. There is no dynamic sixth/seventh overflow PR or custom overflow
|
||||
bundling requirement.
|
||||
- Onboarding/configuration PRs are outside this dependency-PR limit and precede
|
||||
ordinary dependency proposals.
|
||||
- Renovate creates and updates proposals only. Maintainers review the change and
|
||||
CI result and merge manually; automerge is disabled.
|
||||
|
||||
## Lockfile maintenance
|
||||
|
||||
- Ordinary manifest updates include the matching lockfile changes in the same
|
||||
PR, so reproducible installation remains valid.
|
||||
- Separately maintain lockfiles within the existing manifest boundaries on a
|
||||
branch such as `renovate/minor-patch/lockfile-maintenance`.
|
||||
- Keep that maintenance PR separate from ordinary dependency-update PRs and count
|
||||
it within the five-PR limit.
|
||||
- Apply the same seven-day checks to newly resolved/changed versions in that PR.
|
||||
- Do not split a normal manifest update from the lockfile required by that update
|
||||
into separately mergeable, inconsistent proposals.
|
||||
|
||||
## Maintaining existing PRs
|
||||
|
||||
During daily execution, Renovate may refresh existing bot proposals and rebase
|
||||
them when the base branch changes. Refreshed candidates must again pass age and
|
||||
compatibility checks.
|
||||
|
||||
Do not overwrite manual changes on bot branches. If manual edits or conflicts
|
||||
prevent safe maintenance, preserve those edits and show that maintainer action is
|
||||
required in the dashboard.
|
||||
|
||||
## Visibility and management
|
||||
|
||||
- Provide a Dependency Dashboard issue per onboarded repository for pending,
|
||||
open and blocked updates and relevant failures.
|
||||
- Explain age, missing metadata and compatibility blockers concretely.
|
||||
- Preserve execution logs and the result of each scheduled run for **thirty days**,
|
||||
with rotation/retention configured and secret values omitted/redacted.
|
||||
- Retain operational failure information on the Synology even if startup or Gitea
|
||||
connectivity fails before repository processing can update a dashboard.
|
||||
- Provide a management guide covering bot access and secret locations, repository
|
||||
discovery/exclusions and onboarding, schedule/timezone, manual execution,
|
||||
dashboards/logs, configuration validation and recovery.
|
||||
- Document project compatibility maintenance, the manual runner version/checksum
|
||||
boundary, blocked unsupported metadata, manual host/runtime updates and applying
|
||||
an approved Renovate-image version to the running installation.
|
||||
|
||||
## Acceptance criteria
|
||||
|
||||
- [ ] A working Renovate container and daily 06:00 Europe/Amsterdam schedule run
|
||||
on the existing linux/amd64 Synology.
|
||||
- [ ] Discovery covers authorized Gitea repositories, respects exclusions and
|
||||
requires onboarding/configuration approval before dependency proposals.
|
||||
- [ ] This project has a reviewed `renovate.json` with explicit framework and
|
||||
dependency boundaries; compatible managed dependency surfaces are detected.
|
||||
- [ ] Direct, security and new/changed transitive lockfile versions younger than
|
||||
seven days cannot enter new or refreshed bot PRs.
|
||||
- [ ] Unknown release ages block proposals visibly; internal dependencies do not
|
||||
bypass the waiting period.
|
||||
- [ ] Validation proves repository overrides, security defaults and error/fallback
|
||||
paths cannot create or update an ineligible PR.
|
||||
- [ ] Node.js, TypeScript and RxJS updates stay inside the maintainer-controlled
|
||||
Angular compatibility bounds, including any permitted major upgrades.
|
||||
- [ ] Angular and Angular-major-aligned library major upgrades are not proposed;
|
||||
compatible minor/patch changes and coupled package/image references remain
|
||||
coherent.
|
||||
- [ ] Independent proposals and permitted coherent groups use the agreed
|
||||
renovate/major/... and renovate/minor-patch/... branch conventions.
|
||||
- [ ] Major proposals remain separate from unrelated minor/patch updates.
|
||||
- [ ] No more than five dependency PRs are open per repository, including lockfile
|
||||
maintenance; remaining candidates wait rather than form overflow PRs.
|
||||
- [ ] Normal manifest PRs include matching lockfiles; separate lockfile maintenance
|
||||
stays within manifest ranges and satisfies the same age policy.
|
||||
- [ ] Daily maintenance preserves manual branch edits and reports conflicts;
|
||||
merging and actual host/container upgrades remain manual.
|
||||
- [ ] The runner binary version/checksum is explicitly documented as manual, with
|
||||
no partial or incorrect automated checksum updates.
|
||||
- [ ] Dashboards expose repository-level state; thirty-day logs also expose
|
||||
failures before repository processing without disclosing secrets.
|
||||
- [ ] Management documentation and real execution/PR evidence demonstrate the
|
||||
operational setup and enforcement. Configuration files alone are insufficient.
|
||||
|
||||
## Implementation handoff
|
||||
|
||||
This specification records agreed behavior. It does not create the bot account,
|
||||
configure credentials, deploy a container, install a schedule or create PRs/issues.
|
||||
Those actions, any necessary additional age validation and the operational evidence
|
||||
are implementation work. S5 is complete only when its behavior has been proven on
|
||||
the working installation.
|
||||
|
||||
|
||||
Affected repositories: `agiledancers`.
|
||||
Reference in New Issue
Block a user