--- title: SolverForge Field Service Routing emoji: 🧰 colorFrom: indigo colorTo: blue sdk: docker app_port: 7860 pinned: false license: apache-2.0 short_description: SolverForge field-service routing example --- # SolverForge FSR `solverforge-fsr` is a SolverForge field-service routing example with retained jobs, route geometry, technician schedules, and a browser map workspace. It answers one concrete question: "Given technicians, service visits, skills, parts, shifts, territories, and road-network travel, which technician should serve each visit and in what order?" ## Hugging Face Space Deployment This repo is Docker-Space ready. Hugging Face reads the README front matter, builds `Dockerfile`, and expects the app to bind `PORT=7860`. Local Space-equivalent commands: ```sh make space-build make space-run ``` Full local readiness check: ```sh make ci-local ``` The Space image is self-contained: it builds against published crates.io packages, copies `static/`, `solver.toml`, and `solverforge.app.toml`, and runs the release binary `solverforge_fsr`. ## Versioning The app package version is `1.0.1`; the release binary is `solverforge_fsr`. - CLI version used to scaffold this project: `2.0.3` - SolverForge runtime target for this scaffold: `solverforge 0.11.1` - SolverForge UI target for this scaffold: `solverforge-ui 0.6.5` - SolverForge maps target for this scaffold: `solverforge-maps 2.1.4` - Runtime dependency currently wired into `Cargo.toml`: `crates.io: solverforge 0.11.1` - Frontend UI dependency currently wired into `Cargo.toml`: `crates.io: solverforge-ui 0.6.5` - Maps dependency currently wired into `Cargo.toml`: `crates.io: solverforge-maps 2.1.4` This project was scaffolded by `solverforge-cli`, and it currently targets `SolverForge crate target 0.11.1` through the configured crate dependency targets. `solverforge-core` is a direct dependency because the 0.11 custom incremental-constraint API exposes `ConstraintRef`, while the top-level facade does not re-export that type. ## What SolverForge Is Doing Here - `ServiceVisit` is a problem fact: a customer job the solver must place in a technician route. - `TechnicianRoute` is the planning entity: each technician owns one mutable route. - `TechnicianRoute.visits` is the list planning variable. - `FieldServicePlan` is the planning solution. - Constraints score assignment coverage, route reachability, shift capacity, required skills, required parts, time windows, priority slack, territory affinity, travel time, and workload balance. - `solver.toml` selects the construction and local-search policy. The app ships one standard Bergamo field-service dataset and prepares full routing data when a job is created so snapshots can expose per-segment geometry. ## Quick Start ```sh make run-release ``` Then open `http://localhost:7860`. To inspect the command surface: ```sh make help ``` ## Development ```sh # Add a new constraint solverforge generate constraint my_rule --unary --hard # Add a domain entity solverforge generate entity worker --planning-variable shift_idx # Add a problem fact solverforge generate fact location # Remove a resource solverforge destroy constraint my_rule ``` ## Project Structure | Directory | Purpose | |-----------|--------| | `src/domain/` | Planning entities, facts, and solution struct | | `src/constraints/` | Constraint definitions (scored by the solver) | | `src/solver/` | Solver service and configuration | | `src/api/` | HTTP routes and DTOs | | `src/data/` | Data loading and generation | | `static/` | Browser UI, SolverForge UI config, and generated UI model | | `Dockerfile` | Multi-stage Rust 1.95 Alpine build for the Hugging Face Docker Space | | `Makefile` | Local development, validation, and Space image commands | | `solverforge.app.toml` | Scaffolded app/domain contract | | `solver.toml` | Solver configuration (termination, phases) | ## REST API - `GET /health` - `GET /info` - `GET /demo-data` - `GET /demo-data/{id}` - `POST /jobs` - `GET /jobs/{id}` - `GET /jobs/{id}/status` - `GET /jobs/{id}/snapshot` - `GET /jobs/{id}/analysis` - `GET /jobs/{id}/routes` - `POST /jobs/{id}/pause` - `POST /jobs/{id}/resume` - `POST /jobs/{id}/cancel` - `DELETE /jobs/{id}` - `GET /jobs/{id}/events` Route geometry is returned by `/jobs/{id}/routes` with segment-level geometry status. Unreachable road-network legs are reported as non-routed segments, so one infeasible leg does not hide the rest of the snapshot geometry. ## Validation Standard validation: ```sh make test ``` Full local Space validation: ```sh make ci-local ```