Skip to content

chore: make constraint metadata more flexible#2234

Merged
triceo merged 1 commit intoTimefoldAI:mainfrom
triceo:constraintId
Apr 15, 2026
Merged

chore: make constraint metadata more flexible#2234
triceo merged 1 commit intoTimefoldAI:mainfrom
triceo:constraintId

Conversation

@triceo
Copy link
Copy Markdown
Collaborator

@triceo triceo commented Apr 14, 2026

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Introduces the new ConstraintDescription-based metadata model for constraints (IDs + extensible user-defined metadata), updates internal usages (benchmarks, Quarkus/Jackson integrations, metrics tags, tests), and adds a migration recipe plus documentation to support upgrading from earlier APIs.

Changes:

  • Replace string-based constraint name/group/description APIs with ConstraintDescription and rename “constraint name” to “constraint ID”.
  • Update metrics/tagging, serializers, benchmark reporting, and tests to use ConstraintRef.id() and constraint IDs.
  • Add an OpenRewrite migration recipe (and docs) to help migrate removed/renamed constraint metadata APIs.

Reviewed changes

Copilot reviewed 68 out of 68 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
tools/migration/src/test/java/ai/timefold/solver/migration/v2/ConstraintDescriptionMigrationRecipeTest.java Adds recipe tests for the new constraint metadata migration behavior.
tools/migration/src/main/java/ai/timefold/solver/migration/v2/ConstraintDescriptionMigrationRecipe.java New OpenRewrite recipe to migrate removed/renamed constraint metadata APIs.
tools/migration/src/main/java/ai/timefold/solver/migration/ToLatestRecipe.java Wires the new migration recipe into the “to latest” upgrade chain.
tools/benchmark/src/test/java/ai/timefold/solver/benchmark/impl/statistic/subsingle/constraintmatchtotalstepscore/ConstraintMatchTotalStepScoreSubSingleStatisticTest.java Updates benchmark statistic tests to use constraint IDs.
tools/benchmark/src/test/java/ai/timefold/solver/benchmark/impl/statistic/subsingle/constraintmatchtotalbestscore/ConstraintMatchTotalBestScoreSubSingleStatisticTest.java Updates benchmark statistic tests to use constraint IDs.
tools/benchmark/src/main/java/ai/timefold/solver/benchmark/impl/statistic/subsingle/constraintmatchtotalstepscore/ConstraintMatchTotalStepScoreSubSingleStatistic.java Updates chart series labels to use constraint IDs.
tools/benchmark/src/main/java/ai/timefold/solver/benchmark/impl/statistic/subsingle/constraintmatchtotalstepscore/ConstraintMatchTotalStepScoreStatisticPoint.java Updates CSV output to use constraint IDs.
tools/benchmark/src/main/java/ai/timefold/solver/benchmark/impl/statistic/subsingle/constraintmatchtotalbestscore/ConstraintMatchTotalBestScoreSubSingleStatistic.java Updates chart series labels to use constraint IDs.
tools/benchmark/src/main/java/ai/timefold/solver/benchmark/impl/statistic/subsingle/constraintmatchtotalbestscore/ConstraintMatchTotalBestScoreStatisticPoint.java Updates CSV output to use constraint IDs.
tools/benchmark/src/main/java/ai/timefold/solver/benchmark/impl/statistic/StatisticRegistry.java Renames Micrometer tag from constraint.name to constraint.id and adapts extraction logic.
quarkus-integration/quarkus/runtime/src/main/java/ai/timefold/solver/quarkus/devui/TimefoldDevUIPropertiesRPCService.java Exposes constraint IDs (not names) in Dev UI constraints endpoint.
quarkus-integration/quarkus-jackson/runtime/src/main/java/ai/timefold/solver/quarkus/jackson/score/constraint/ConstraintRefJacksonSerializer.java Serializes ConstraintRef using id().
quarkus-integration/quarkus-jackson/runtime/src/main/java/ai/timefold/solver/quarkus/jackson/domain/solution/ConstraintWeightOverridesSerializer.java Serializes weight overrides keyed by constraint IDs.
quarkus-integration/quarkus-jackson/runtime/src/main/java/ai/timefold/solver/quarkus/jackson/domain/solution/AbstractConstraintWeightOverridesDeserializer.java Deserializes weight overrides into ID-keyed map.
persistence/jackson/src/main/java/ai/timefold/solver/jackson/api/score/constraint/ConstraintRefJacksonSerializer.java Serializes ConstraintRef using id().
persistence/jackson/src/main/java/ai/timefold/solver/jackson/api/domain/solution/ConstraintWeightOverridesSerializer.java Serializes weight overrides keyed by constraint IDs.
persistence/jackson/src/main/java/ai/timefold/solver/jackson/api/domain/solution/AbstractConstraintWeightOverridesDeserializer.java Deserializes weight overrides into ID-keyed map.
docs/src/modules/ROOT/pages/using-timefold-solver/running-the-solver.adoc Updates Micrometer tag documentation to constraint.id.
docs/src/modules/ROOT/pages/upgrading-timefold-solver/upgrade-from-v1.adoc Documents upgrade path for constraint ID/description/group API changes.
docs/src/modules/ROOT/pages/constraints-and-score/score-calculation.adoc Adds ConstraintDescription metadata model documentation and “constraint anatomy” section updates.
docs/src/modules/ROOT/pages/constraints-and-score/constraint-configuration.adoc Clarifies that ConstraintWeightOverrides keys must match constraint IDs.
core/src/test/java/ai/timefold/solver/core/testconstraint/TestConstraint.java Updates test constraint construction to use DefaultConstraintDescription instead of group/description strings.
core/src/test/java/ai/timefold/solver/core/impl/score/stream/common/uni/UniConstraintBuilderTest.java Updates builder tests for new constraint construction signature.
core/src/test/java/ai/timefold/solver/core/impl/score/stream/common/uni/AbstractUniConstraintStreamTest.java Replaces test constraint name usage with constraint ID.
core/src/test/java/ai/timefold/solver/core/impl/score/stream/common/uni/AbstractUniConstraintStreamPrecomputeTest.java Replaces test constraint name usage with constraint ID.
core/src/test/java/ai/timefold/solver/core/impl/score/stream/common/tri/TriConstraintBuilderTest.java Updates builder tests for new constraint construction signature.
core/src/test/java/ai/timefold/solver/core/impl/score/stream/common/tri/AbstractTriConstraintStreamTest.java Replaces test constraint name usage with constraint ID.
core/src/test/java/ai/timefold/solver/core/impl/score/stream/common/tri/AbstractTriConstraintStreamPrecomputeTest.java Replaces test constraint name usage with constraint ID.
core/src/test/java/ai/timefold/solver/core/impl/score/stream/common/quad/QuadConstraintBuilderTest.java Updates builder tests for new constraint construction signature.
core/src/test/java/ai/timefold/solver/core/impl/score/stream/common/quad/AbstractQuadConstraintStreamTest.java Replaces test constraint name usage with constraint ID.
core/src/test/java/ai/timefold/solver/core/impl/score/stream/common/quad/AbstractQuadConstraintStreamPrecomputeTest.java Replaces test constraint name usage with constraint ID.
core/src/test/java/ai/timefold/solver/core/impl/score/stream/common/bi/BiConstraintBuilderTest.java Updates builder tests for new constraint construction signature.
core/src/test/java/ai/timefold/solver/core/impl/score/stream/common/bi/AbstractBiConstraintStreamTest.java Replaces test constraint name usage with constraint ID.
core/src/test/java/ai/timefold/solver/core/impl/score/stream/common/bi/AbstractBiConstraintStreamPrecomputeTest.java Replaces test constraint name usage with constraint ID.
core/src/test/java/ai/timefold/solver/core/impl/score/stream/common/AbstractConstraintTest.java Removes constraint group validation tests (constraint groups removed).
core/src/test/java/ai/timefold/solver/core/impl/score/stream/common/AbstractConstraintStreamTest.java Renames shared test constants from “name” to “id” and updates match helpers.
core/src/test/java/ai/timefold/solver/core/impl/score/stream/common/AbstractAdvancedGroupByConstraintStreamTest.java Updates test constraints to use constraint IDs.
core/src/test/java/ai/timefold/solver/core/impl/score/stream/bavet/BavetRegressionTest.java Updates regression tests to use constraint IDs.
core/src/test/java/ai/timefold/solver/core/impl/score/stream/bavet/BavetAdvancedGroupByConstraintStreamTest.java Updates Bavet group-by tests to use constraint IDs.
core/src/test/java/ai/timefold/solver/core/impl/score/stream/AbstractConstraintBuilderTest.java Refactors sanitization tests to validate constraint IDs via asConstraint(id).
core/src/test/java/ai/timefold/solver/core/impl/score/director/stream/DefaultConstraintMetaModelTest.java Removes group-related meta model assertions and updates test constraints accordingly.
core/src/test/java/ai/timefold/solver/core/impl/domain/solution/ConstraintWeightOverridesTest.java Renames API usage from known constraint names to known constraint IDs.
core/src/main/java/ai/timefold/solver/core/impl/score/stream/test/AbstractSingleConstraintAssertion.java Updates assertion messages to use constraint IDs.
core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/DefaultConstraintDescription.java Adds default ConstraintDescription implementation used by asConstraint(String).
core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/ConstraintConstructor.java Updates constraint construction functional interface to accept ConstraintDescription.
core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/AbstractConstraintBuilder.java Changes terminal builder API to asConstraint(ConstraintDescription).
core/src/main/java/ai/timefold/solver/core/impl/score/stream/common/AbstractConstraint.java Stores ConstraintDescription, derives ConstraintRef from description.id(), and removes constraint group handling.
core/src/main/java/ai/timefold/solver/core/impl/score/stream/bavet/uni/BavetAbstractUniConstraintStream.java Updates constraint build pipeline to pass ConstraintDescription.
core/src/main/java/ai/timefold/solver/core/impl/score/stream/bavet/tri/BavetAbstractTriConstraintStream.java Updates constraint build pipeline to pass ConstraintDescription.
core/src/main/java/ai/timefold/solver/core/impl/score/stream/bavet/quad/BavetAbstractQuadConstraintStream.java Updates constraint build pipeline to pass ConstraintDescription.
core/src/main/java/ai/timefold/solver/core/impl/score/stream/bavet/bi/BavetAbstractBiConstraintStream.java Updates constraint build pipeline to pass ConstraintDescription.
core/src/main/java/ai/timefold/solver/core/impl/score/stream/bavet/BavetConstraint.java Updates constraint implementation constructor to accept ConstraintDescription.
core/src/main/java/ai/timefold/solver/core/impl/score/director/stream/DefaultConstraintMetaModel.java Removes group indexing and simplifies meta model to map by ConstraintRef.
core/src/main/java/ai/timefold/solver/core/impl/score/director/InnerScoreDirector.java Updates Javadoc to refer to constraint IDs.
core/src/main/java/ai/timefold/solver/core/impl/score/constraint/ConstraintMatch.java Uses constraint IDs in toString().
core/src/main/java/ai/timefold/solver/core/impl/localsearch/DefaultLocalSearchPhase.java Updates Micrometer tags to use constraint.id.
core/src/main/java/ai/timefold/solver/core/impl/domain/solution/descriptor/ConstraintWeightSupplier.java Validates overrides against constraint IDs and queries weights by ID.
core/src/main/java/ai/timefold/solver/core/impl/domain/solution/DefaultConstraintWeightOverrides.java Renames API to getKnownConstraintIds() and uses ID-based lookup.
core/src/main/java/ai/timefold/solver/core/impl/bavet/visual/NodeGraph.java Displays constraint IDs in DOT metadata output.
core/src/main/java/ai/timefold/solver/core/impl/bavet/common/BavetAbstractConstraintStream.java Builds constraints from ConstraintDescription rather than separate name/group/description strings.
core/src/main/java/ai/timefold/solver/core/api/score/stream/ConstraintRef.java Renames record component to id and sanitizes ID via sanitize("id", ...).
core/src/main/java/ai/timefold/solver/core/api/score/stream/ConstraintMetaModel.java Removes group APIs and adds shorthand getConstraint(String id).
core/src/main/java/ai/timefold/solver/core/api/score/stream/ConstraintDescription.java Introduces user-extensible constraint metadata interface with immutable ID contract.
core/src/main/java/ai/timefold/solver/core/api/score/stream/ConstraintBuilder.java Replaces asConstraintDescribed(...) with asConstraint(String) and asConstraint(ConstraintDescription).
core/src/main/java/ai/timefold/solver/core/api/score/stream/Constraint.java Removes group APIs and changes getDescription() return type to ConstraintDescription.
core/src/main/java/ai/timefold/solver/core/api/score/analysis/ScoreAnalysis.java Renames constraint analysis lookup parameter to constraintId.
core/src/main/java/ai/timefold/solver/core/api/score/analysis/ConstraintAnalysis.java Replaces constraintName() with default constraintId() based on constraintRef().id().
core/src/main/java/ai/timefold/solver/core/api/domain/solution/ConstraintWeightOverrides.java Renames APIs to ID-based naming and adds overload for ConstraintRef.

Comment thread docs/src/modules/ROOT/pages/constraints-and-score/score-calculation.adoc Outdated
Comment thread docs/src/modules/ROOT/pages/constraints-and-score/score-calculation.adoc Outdated
Copy link
Copy Markdown
Contributor

@zepfred zepfred left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new code improved the cohesion, and the class ConstraintDescription is an good solution. However, I don't understand why the class lacks description information. In my opinion, both ID and description should be the key information regarding the constraints.

@triceo
Copy link
Copy Markdown
Collaborator Author

triceo commented Apr 15, 2026

The goal of this PR is for the solver to only expose what the solver needs - and the solver only needs id. There are literally zero consumers of the name, the description, or the group. All of these fields were introduced for the platform, and the platform now needs more fields than this; so we agreed that they would get this mechanism instead.

Description will not be on the interface, because there is no need for us to provide any.

Copilot AI review requested due to automatic review settings April 15, 2026 15:21
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 70 out of 70 changed files in this pull request and generated no new comments.

@sonarqubecloud
Copy link
Copy Markdown

@triceo triceo merged commit c697e85 into TimefoldAI:main Apr 15, 2026
22 checks passed
@triceo triceo deleted the constraintId branch April 15, 2026 16:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants