Use the scaffold as a thin starter, then model the real problem in your app.
- Add entities, problem facts, and planning variables for the real data shape.
- Use field metadata to model scalar variables and one or more independent list owners in the same project when needed.
- Scalar
#[planning_variable]fields are candidate indexes and must beOption<usize>. Keep external IDs on problem facts or entities, and map them through the value range provider collection. - Use
#[planning_list_variable(element_collection = "elements")]when the solver decides both ownership and order. The owning entity stores aVec<usize>of element indexes; list-aware construction and neighborhoods preserve the sequence representation. Configure inverse, index, previous, next, custom, cascading, or piggyback shadows when the application needs derived views of that list state. For example,#[shadow_variable_updates(list_owner = "routes", index_field = "index")]keeps anOption<usize>element field synchronized with its current list position. - Keep
src/domain/mod.rsas asolverforge::planning_model!manifest withroot = "src/domain", normalmod name;declarations, and the public exports for the model. Entity, fact, and solution files stay separate. - Keep normal Rust module organization. SolverForge does not require entity
modules to be declared before solution modules; scalar runtime metadata is
generated from descriptor order and variable names, not expansion order. The
compact scalar
variable_indexremains an internal getter/setter index. - Public aliases are fine at the Rust boundary, including
type Alias = Type;andpub use module::Type as Alias;. Solver configuration targets still use the canonical descriptor type name, not the alias used by a collection field. - When a scalar variable will use nearby local-search selectors, declare the
nearby candidate hook directly on that variable so the solver policy stays
explicit and model-owned. Use
nearby_value_candidatesfor nearby scalar change andnearby_entity_candidatesfor nearby scalar swap. - Use
candidate_valueswhen construction, scalar change, pillar change, or scalar ruin-recreate should consume an ordered bounded value neighborhood instead of the full legal domain. - When a scalar construction heuristic needs sorted entity or value order,
declare that on the same
#[planning_variable]withconstruction_entity_order_key = "fn_name"and/orconstruction_value_order_key = "fn_name". - Keep stock CVRP routing declarative with
#[planning_list_variable(element_collection = "...", domain = "cvrp")]. The profile wires the stock route-local and Clarke-Wright construction hooks internally. Route-local phases use strict stock CVRP capacity and time-window feasibility, while Clarke-Wright construction uses relaxed savings feasibility so the score model can compare capacity, lateness, travel-time, and unassigned penalties after assignment. - Omit
domain = "cvrp"and use explicitroute_hooks = "path"andsavings_hooks = "path"only for custom routing domains or strict pruning policies. The route-local module must exportget,set,depot,distance, andfeasible; the savings module must exportdepot,distance, andfeasible. Addsavings_metric_class_fn = "path::metric_class"only when owners share construction depot and distance behavior. - Add derived fields, validation helpers, and sample data beside the domain model, not in the scaffold templates.
- Use
nearby_entity_distance_meterornearby_value_distance_meteronly to rank or filter the bounded nearby candidates. A distance meter by itself does not bound candidate generation. - Use
construction_entity_order_keywhen construction must rank entities before generating placements. - Use
construction_value_order_keywhen construction must rank candidate values per entity, such as weakest-fit, strongest-fit, or queue-style allocation. - Keep these separate. Nearby hooks guide local-search neighborhood shape; construction order keys guide construction-phase ordering and are not read by local-search scalar selectors.
- Create app-specific modules for larger domain logic.
- Move example constraints and sample fixtures into the app once they stop being representative of the starter project.
- Keep the generated scaffold thin so it stays a starter, not the source of truth.
- Keep the scaffolded project.
- Add your real entities, facts, and variable declarations.
- Replace example data and example constraints with production domain logic.
- Split large domain code into app modules as it grows.