Spaces:
Sleeping
docs: document deliveries tutorial and Space workflow
Browse filesDocument the current deliveries tutorial surface end to end. The README now includes Hugging Face Space front matter, the dependency and Rust-version line, the SolverForge domain concepts, the validation commands, Space build/run commands, the code reading order, REST routes, routing modes, solver policy, and the current ten-vehicle demo dataset sizes.
Add AGENTS.md as the repo-local editing contract. It records the canonical Plan naming, file-size rule, no-suppression policy, Makefile workflow, documentation alignment requirements, road-network test gating, published dependency policy, and retained-job runtime notes.
Add WIREFRAME.md as the architecture map for future work. It explains the runtime flow from browser boot through demo data, preparation, retained solving, SSE, snapshots, route geometry, and frontend rendering; it also maps the files by responsibility and describes the domain, route-metrics, API, frontend, and validation surfaces.
This is a documentation-only boundary. Reverting it leaves the app, tests, and Space tooling intact while removing the tutorial prose and contributor guidance.
- AGENTS.md +92 -0
- README.md +250 -0
- WIREFRAME.md +229 -0
|
@@ -0,0 +1,92 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Repository Guidelines
|
| 2 |
+
|
| 3 |
+
## Project Structure And Naming
|
| 4 |
+
|
| 5 |
+
This repo follows the current `solverforge-cli` app shape. The app package
|
| 6 |
+
version is `1.0.0`, and the release binary is `solverforge_deliveries`.
|
| 7 |
+
|
| 8 |
+
- `src/domain/mod.rs` owns the `solverforge::planning_model!` manifest.
|
| 9 |
+
- `src/domain/plan.rs` owns the `Plan` planning solution.
|
| 10 |
+
- `src/domain/delivery.rs` owns the `Delivery` problem fact.
|
| 11 |
+
- `src/domain/vehicle.rs` owns the `Vehicle` planning entity and its
|
| 12 |
+
`delivery_order` list variable.
|
| 13 |
+
- `src/domain/preview.rs` owns transport/view preview structs.
|
| 14 |
+
- `src/domain/route_metrics/` owns route preparation, CVRP hooks, scoring
|
| 15 |
+
preview, route geometry, and insertion ranking.
|
| 16 |
+
- `src/constraints/` owns one score rule per file plus `mod.rs` assembly.
|
| 17 |
+
- `src/data/data_seed/` owns deterministic city demo-data modules with grouped
|
| 18 |
+
visit files for scaled delivery counts.
|
| 19 |
+
- `src/api/` owns REST, DTO, and SSE surfaces.
|
| 20 |
+
- `src/solver/` owns retained-job runtime orchestration.
|
| 21 |
+
- `static/app/models/` owns frontend plan modeling.
|
| 22 |
+
- `static/app/ui/` owns browser layout and rendering helpers.
|
| 23 |
+
|
| 24 |
+
Keep the canonical solution name `Plan`. Do not reintroduce `DeliveryPlan` or
|
| 25 |
+
`delivery_plan.rs`.
|
| 26 |
+
|
| 27 |
+
## File Size Rule
|
| 28 |
+
|
| 29 |
+
No source, test, frontend, config, or repo documentation file should reach 300
|
| 30 |
+
lines. Split by responsibility before that point. Large generated/cache output
|
| 31 |
+
under `target/` and `.osm_cache/` is outside this rule.
|
| 32 |
+
|
| 33 |
+
## Build And Validation Commands
|
| 34 |
+
|
| 35 |
+
- `make help` shows the supported command surface.
|
| 36 |
+
- `make run-release` runs the app locally on `:7860`.
|
| 37 |
+
- `make test` runs Rust, frontend, and Playwright browser tests.
|
| 38 |
+
- `make test-e2e` runs the real browser Playwright smoke.
|
| 39 |
+
- `make space-build` builds the Docker image used by Hugging Face Spaces.
|
| 40 |
+
- `make space-run` builds and runs that image locally.
|
| 41 |
+
- `make ci-local` runs formatting, clippy, release build, standard tests, and
|
| 42 |
+
the Space Docker image build.
|
| 43 |
+
- `make test-live-road` runs the env-enabled road-network smoke test.
|
| 44 |
+
- `make pre-release` runs `ci-local` and the live road-network smoke.
|
| 45 |
+
- `cargo test` runs Rust unit and integration tests.
|
| 46 |
+
- `node --test tests/frontend_models.test.mjs` runs frontend model tests.
|
| 47 |
+
|
| 48 |
+
Use the Makefile as the authoritative local workflow, matching the
|
| 49 |
+
`solverforge-hospital` Space/Docker validation standard.
|
| 50 |
+
|
| 51 |
+
## No Suppression Policy
|
| 52 |
+
|
| 53 |
+
Do not add warning suppressions, fallback compatibility branches, or unused
|
| 54 |
+
helper modules. If a split creates unused code, restructure the modules so each
|
| 55 |
+
compiled item is used by its crate.
|
| 56 |
+
|
| 57 |
+
## Documentation Policy
|
| 58 |
+
|
| 59 |
+
Keep `Cargo.toml`, `Cargo.lock`, `Makefile`, `Dockerfile`, `README.md`,
|
| 60 |
+
`WIREFRAME.md`, `AGENTS.md`, `solverforge.app.toml`, `solver.toml`,
|
| 61 |
+
`static/sf-config.json`, and the visible API guide in
|
| 62 |
+
`static/app/ui/api-guide.mjs` aligned.
|
| 63 |
+
|
| 64 |
+
When changing routes, solver policy, demo IDs, dependency sources, file layout,
|
| 65 |
+
or browser behavior, update the docs in the same patch. Prefer current-state
|
| 66 |
+
documentation over planning language.
|
| 67 |
+
|
| 68 |
+
## Testing Guidance
|
| 69 |
+
|
| 70 |
+
Add Rust unit tests next to the behavior they protect. Add API integration
|
| 71 |
+
coverage under `tests/api_contract/` and shared integration helpers under
|
| 72 |
+
`tests/support/` only when every helper is used by the single
|
| 73 |
+
`tests/api_contract.rs` crate. Add frontend model tests in
|
| 74 |
+
`tests/frontend_models.test.mjs`, and browser-flow tests in `tests/e2e/`.
|
| 75 |
+
|
| 76 |
+
Road-network tests should stay env-gated unless the test uses only cached or
|
| 77 |
+
straight-line behavior. Use `SOLVERFORGE_RUN_LIVE_TESTS=1` through
|
| 78 |
+
`make test-live-road` when validating live map/routing paths.
|
| 79 |
+
|
| 80 |
+
## Runtime Notes
|
| 81 |
+
|
| 82 |
+
`solver.toml` is embedded by `Plan` through the planning-solution macro. Treat
|
| 83 |
+
it as the solver policy source of truth.
|
| 84 |
+
|
| 85 |
+
`Cargo.toml` currently uses Rust `1.95` and published crates.io dependencies
|
| 86 |
+
only. Keep every direct dependency declaration at the latest published version,
|
| 87 |
+
and keep `solverforge.app.toml`, `Cargo.lock`, and docs truthful if those
|
| 88 |
+
dependency sources or versions change.
|
| 89 |
+
|
| 90 |
+
The app serves stock `solverforge-ui` assets, local static app modules, and
|
| 91 |
+
Axum API routes from one process. Retained solver jobs are controlled through
|
| 92 |
+
REST and observed through SSE.
|
|
@@ -0,0 +1,250 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: SolverForge Deliveries
|
| 3 |
+
emoji: π
|
| 4 |
+
colorFrom: green
|
| 5 |
+
colorTo: blue
|
| 6 |
+
sdk: docker
|
| 7 |
+
app_port: 7860
|
| 8 |
+
pinned: false
|
| 9 |
+
license: apache-2.0
|
| 10 |
+
short_description: SolverForge delivery-route optimization example
|
| 11 |
+
---
|
| 12 |
+
|
| 13 |
+
# SolverForge Deliveries
|
| 14 |
+
|
| 15 |
+
`solverforge-deliveries` is a SolverForge vehicle-routing example with retained
|
| 16 |
+
jobs, route geometry, insertion recommendations, and a browser plan viewer.
|
| 17 |
+
|
| 18 |
+
It answers one concrete question:
|
| 19 |
+
|
| 20 |
+
"Given depots, vehicles, delivery stops, capacities, and time windows, which
|
| 21 |
+
vehicle should visit each delivery and in what order?"
|
| 22 |
+
|
| 23 |
+
## Documentation Map
|
| 24 |
+
|
| 25 |
+
- `README.md`
|
| 26 |
+
Quick start, concepts, API surface, and the shortest learning path.
|
| 27 |
+
- `WIREFRAME.md`
|
| 28 |
+
Architecture and request/data flow across backend, runtime, maps, and UI.
|
| 29 |
+
- `AGENTS.md`
|
| 30 |
+
Repo-specific contribution, validation, and documentation rules.
|
| 31 |
+
- `Makefile`
|
| 32 |
+
The supported local command surface for development, validation, and
|
| 33 |
+
Docker-based Hugging Face Space preparation.
|
| 34 |
+
- `Dockerfile`
|
| 35 |
+
The Docker Space image build, using Rust 1.95 and published crates.io
|
| 36 |
+
dependencies.
|
| 37 |
+
|
| 38 |
+
## Current Dependency Shape
|
| 39 |
+
|
| 40 |
+
The app package version is `1.0.0`; the release binary is
|
| 41 |
+
`solverforge_deliveries`.
|
| 42 |
+
|
| 43 |
+
This repo requires Rust `1.95` and is configured against published crates.io
|
| 44 |
+
dependencies. Direct dependency declarations use the latest published versions
|
| 45 |
+
checked for this repo:
|
| 46 |
+
|
| 47 |
+
- `solverforge` `0.9.1`
|
| 48 |
+
- `solverforge-ui` `0.6.3`
|
| 49 |
+
- `solverforge-maps` `2.1.3`
|
| 50 |
+
- `axum` `0.8.9`
|
| 51 |
+
- `tokio` `1.52.1`
|
| 52 |
+
- `tokio-stream` `0.1.18`
|
| 53 |
+
- `tower-http` `0.6.8`
|
| 54 |
+
- `tower` `0.5.3`
|
| 55 |
+
- `serde` `1.0.228`
|
| 56 |
+
- `serde_json` `1.0.149`
|
| 57 |
+
- `rand` `0.10.1`
|
| 58 |
+
- `uuid` `1.23.1`
|
| 59 |
+
- `parking_lot` `0.12.5`
|
| 60 |
+
- `http-body-util` `0.1.3`
|
| 61 |
+
|
| 62 |
+
The app metadata in `solverforge.app.toml` mirrors that published dependency
|
| 63 |
+
shape and records `solverforge-cli` `2.0.0` as the current scaffold metadata
|
| 64 |
+
line.
|
| 65 |
+
|
| 66 |
+
## What SolverForge Is Doing Here
|
| 67 |
+
|
| 68 |
+
- `Delivery` is a problem fact: a stop the solver must place in a route.
|
| 69 |
+
- `Vehicle` is a planning entity: each vehicle owns one mutable route.
|
| 70 |
+
- `Vehicle.delivery_order` is the list planning variable.
|
| 71 |
+
- `Plan` is the planning solution, matching the current `solverforge-cli`
|
| 72 |
+
default solution name and `src/domain/plan.rs` file shape.
|
| 73 |
+
- Constraints score assignment coverage, capacity, time-window violations, and
|
| 74 |
+
total travel time.
|
| 75 |
+
- `solver.toml` selects list construction heuristics and local-search moves.
|
| 76 |
+
|
| 77 |
+
The app ships three city datasets:
|
| 78 |
+
|
| 79 |
+
- `PHILADELPHIA` (default)
|
| 80 |
+
- `HARTFORD`
|
| 81 |
+
- `FIRENZE`
|
| 82 |
+
|
| 83 |
+
Each dataset has ten vehicles: 82 Philadelphia deliveries, 50 Hartford
|
| 84 |
+
deliveries, and 80 Firenze deliveries. Philadelphia is the default road-network
|
| 85 |
+
baseline, and all current seed data has enough aggregate vehicle capacity and
|
| 86 |
+
reachable street-front coordinates for the configured delivery stops.
|
| 87 |
+
|
| 88 |
+
## Quick Start
|
| 89 |
+
|
| 90 |
+
```sh
|
| 91 |
+
make run-release
|
| 92 |
+
```
|
| 93 |
+
|
| 94 |
+
Then open `http://localhost:7860`.
|
| 95 |
+
|
| 96 |
+
To inspect the command surface:
|
| 97 |
+
|
| 98 |
+
```sh
|
| 99 |
+
make help
|
| 100 |
+
```
|
| 101 |
+
|
| 102 |
+
## Validation
|
| 103 |
+
|
| 104 |
+
Standard validation:
|
| 105 |
+
|
| 106 |
+
```sh
|
| 107 |
+
make test
|
| 108 |
+
```
|
| 109 |
+
|
| 110 |
+
Full local validation:
|
| 111 |
+
|
| 112 |
+
```sh
|
| 113 |
+
make ci-local
|
| 114 |
+
```
|
| 115 |
+
|
| 116 |
+
Space image validation:
|
| 117 |
+
|
| 118 |
+
```sh
|
| 119 |
+
make space-build
|
| 120 |
+
```
|
| 121 |
+
|
| 122 |
+
Live road-network smoke:
|
| 123 |
+
|
| 124 |
+
```sh
|
| 125 |
+
make test-live-road
|
| 126 |
+
```
|
| 127 |
+
|
| 128 |
+
`make test` includes Rust tests, browserless frontend tests, and Playwright
|
| 129 |
+
browser tests. `make ci-local` adds the Docker image build used by the Hugging
|
| 130 |
+
Face Space. `make pre-release` runs `make ci-local` and then the live
|
| 131 |
+
road-network smoke test. The live road test may touch the local `.osm_cache/`
|
| 132 |
+
through `solverforge-maps`; that cache is ignored by git and by Docker builds.
|
| 133 |
+
|
| 134 |
+
## Hugging Face Space Deployment
|
| 135 |
+
|
| 136 |
+
This repo is Docker-Space ready. The Space reads the README front matter,
|
| 137 |
+
builds `Dockerfile`, and expects the app to bind `PORT=7860`.
|
| 138 |
+
|
| 139 |
+
Local Space-equivalent commands:
|
| 140 |
+
|
| 141 |
+
```sh
|
| 142 |
+
make space-build
|
| 143 |
+
make space-run
|
| 144 |
+
```
|
| 145 |
+
|
| 146 |
+
## Read The Code In This Order
|
| 147 |
+
|
| 148 |
+
1. `src/domain/mod.rs`
|
| 149 |
+
The `planning_model!` manifest and public domain exports.
|
| 150 |
+
2. `src/domain/plan.rs`
|
| 151 |
+
The `Plan` solution and list-variable shadow-refresh wiring.
|
| 152 |
+
3. `src/domain/delivery.rs` and `src/domain/vehicle.rs`
|
| 153 |
+
The fact and planning-entity models.
|
| 154 |
+
4. `src/domain/route_metrics/`
|
| 155 |
+
Route preparation, CVRP hooks, scoring preview, route geometry, and insertion
|
| 156 |
+
ranking.
|
| 157 |
+
5. `src/constraints/mod.rs`
|
| 158 |
+
The constraint-set assembly point.
|
| 159 |
+
6. `src/constraints/*.rs`
|
| 160 |
+
One scoring rule per file.
|
| 161 |
+
7. `src/data/data_seed/entrypoints.rs`
|
| 162 |
+
Public demo-data IDs and generator dispatch.
|
| 163 |
+
8. `src/data/data_seed/{philadelphia,hartford,firenze}/`
|
| 164 |
+
City depots and delivery coordinates.
|
| 165 |
+
9. `src/solver/service.rs`
|
| 166 |
+
Retained-job orchestration over `SolverManager<Plan>`.
|
| 167 |
+
10. `src/api/routes.rs`, `src/api/dto.rs`, and `src/api/sse.rs`
|
| 168 |
+
REST, DTO, and event-stream contracts.
|
| 169 |
+
11. `static/app/main.mjs`
|
| 170 |
+
Browser controller.
|
| 171 |
+
12. `static/app/models/` and `static/app/ui/`
|
| 172 |
+
Frontend plan normalization, preview modeling, layout, maps, tables, and
|
| 173 |
+
modals.
|
| 174 |
+
|
| 175 |
+
## Project Shape
|
| 176 |
+
|
| 177 |
+
- `src/domain/`
|
| 178 |
+
Planning model, domain types, route metrics, and test-only model checks.
|
| 179 |
+
- `src/constraints/`
|
| 180 |
+
Incremental SolverForge scoring rules.
|
| 181 |
+
- `src/data/`
|
| 182 |
+
Deterministic city demo-data generator.
|
| 183 |
+
- `src/solver/`
|
| 184 |
+
Retained-job facade and runtime event payload formatting.
|
| 185 |
+
- `src/api/`
|
| 186 |
+
Axum routes, DTOs, and SSE endpoint.
|
| 187 |
+
- `static/app/`
|
| 188 |
+
Browser modules built on stock `solverforge-ui` assets.
|
| 189 |
+
- `Dockerfile`
|
| 190 |
+
Multi-stage Rust 1.95 Alpine build for the Hugging Face Docker Space.
|
| 191 |
+
- `tests/api_contract/`
|
| 192 |
+
Integration tests for catalog, jobs, lifecycle, SSE, and road-network smoke.
|
| 193 |
+
- `tests/frontend_models.test.mjs`
|
| 194 |
+
Browserless frontend model tests.
|
| 195 |
+
- `tests/e2e/`
|
| 196 |
+
Playwright tests for the served browser app, including asset loading, dataset
|
| 197 |
+
switching, route highlighting, and retained solve start/stop.
|
| 198 |
+
|
| 199 |
+
## REST API
|
| 200 |
+
|
| 201 |
+
- `GET /health`
|
| 202 |
+
- `GET /info`
|
| 203 |
+
- `GET /demo-data`
|
| 204 |
+
- `GET /demo-data/{id}`
|
| 205 |
+
- `POST /jobs`
|
| 206 |
+
- `GET /jobs/{id}`
|
| 207 |
+
- `GET /jobs/{id}/status`
|
| 208 |
+
- `GET /jobs/{id}/snapshot`
|
| 209 |
+
- `GET /jobs/{id}/analysis`
|
| 210 |
+
- `GET /jobs/{id}/routes`
|
| 211 |
+
- `POST /jobs/{id}/pause`
|
| 212 |
+
- `POST /jobs/{id}/resume`
|
| 213 |
+
- `POST /jobs/{id}/cancel`
|
| 214 |
+
- `DELETE /jobs/{id}`
|
| 215 |
+
- `GET /jobs/{id}/events`
|
| 216 |
+
- `POST /recommendations/delivery-insertions`
|
| 217 |
+
|
| 218 |
+
Lifecycle semantics:
|
| 219 |
+
|
| 220 |
+
- `pause` requests a runtime-managed pause and checkpoint.
|
| 221 |
+
- `resume` continues from the retained checkpoint.
|
| 222 |
+
- `cancel` stops a live or paused job.
|
| 223 |
+
- `delete` removes a terminal retained job before the next fresh solve.
|
| 224 |
+
- `snapshot_revision={n}` is optional for snapshots, analysis, and routes.
|
| 225 |
+
- SSE reconnects bootstrap from the retained runtime status/event state.
|
| 226 |
+
|
| 227 |
+
## Routing Modes
|
| 228 |
+
|
| 229 |
+
`road_network` is the default and uses `solverforge-maps` to fetch or load a
|
| 230 |
+
road graph for the current plan bounds. `straight_line` is available as a fast
|
| 231 |
+
draft/testing mode. Route geometry is returned by `/jobs/{id}/routes` and drawn
|
| 232 |
+
in the browser map only when it matches the active snapshot and routing mode.
|
| 233 |
+
The route list can highlight one vehicle route while dimming the rest of the
|
| 234 |
+
map geometry without changing the user's current map viewport.
|
| 235 |
+
|
| 236 |
+
## Solver Policy
|
| 237 |
+
|
| 238 |
+
`solver.toml` is embedded by `Plan` and is the runtime source of truth:
|
| 239 |
+
|
| 240 |
+
- `list_clarke_wright` builds delivery routes.
|
| 241 |
+
- `list_k_opt` improves construction output before local search.
|
| 242 |
+
- local search combines nearby list change/swap, reverse, k-opt, ruin, and
|
| 243 |
+
limited sublist moves.
|
| 244 |
+
- `late_acceptance` and `accepted_count` control acceptance and retained
|
| 245 |
+
candidates.
|
| 246 |
+
|
| 247 |
+
The city seeds have coherent capacity and reachable road-network coordinates so
|
| 248 |
+
local search can reach feasible `0hard` road-network solutions. Current seed
|
| 249 |
+
sizes are 82 Philadelphia deliveries, 50 Hartford deliveries, and 80 Firenze
|
| 250 |
+
deliveries, each with ten vehicles.
|
|
@@ -0,0 +1,229 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# solverforge-deliveries WIREFRAME
|
| 2 |
+
|
| 3 |
+
This file is the architectural map for the deliveries example.
|
| 4 |
+
|
| 5 |
+
`README.md` explains how to run and use the app. This document explains how the
|
| 6 |
+
pieces fit together and where each responsibility lives.
|
| 7 |
+
|
| 8 |
+
## Documentation Roles
|
| 9 |
+
|
| 10 |
+
- `README.md`
|
| 11 |
+
Quick start, dependency shape, route list, and user-facing orientation.
|
| 12 |
+
- `WIREFRAME.md`
|
| 13 |
+
Architecture, execution flow, and file-map walkthrough.
|
| 14 |
+
- `AGENTS.md`
|
| 15 |
+
Repo-specific contribution, validation, and documentation rules.
|
| 16 |
+
- `Makefile`
|
| 17 |
+
Local development, validation, and Space/Docker command surface.
|
| 18 |
+
- `Dockerfile`
|
| 19 |
+
Hugging Face Docker Space image definition.
|
| 20 |
+
|
| 21 |
+
## What This Repo Is Teaching
|
| 22 |
+
|
| 23 |
+
This repo is a complete `solverforge-deliveries` `1.0.0` list-variable
|
| 24 |
+
SolverForge app for delivery routing.
|
| 25 |
+
|
| 26 |
+
It shows how to combine:
|
| 27 |
+
|
| 28 |
+
- a `Plan` solution with a list planning variable
|
| 29 |
+
- route-specific score rules
|
| 30 |
+
- SolverForge CVRP construction and local-search hooks
|
| 31 |
+
- `solverforge-maps` road-network preparation and route geometry
|
| 32 |
+
- retained jobs with snapshots, analysis, cancel, pause, resume, and SSE
|
| 33 |
+
- a browser plan viewer built on stock `solverforge-ui` assets
|
| 34 |
+
|
| 35 |
+
## SolverForge Concepts In Plain Language
|
| 36 |
+
|
| 37 |
+
- `Delivery`
|
| 38 |
+
Input stop data. The solver assigns delivery IDs into vehicle routes.
|
| 39 |
+
- `Vehicle`
|
| 40 |
+
Planning entity. Each vehicle owns one ordered `delivery_order` list.
|
| 41 |
+
- `Plan`
|
| 42 |
+
Planning solution. It holds deliveries, vehicles, score, routing mode, view
|
| 43 |
+
state, and prepared routing data.
|
| 44 |
+
- hard score
|
| 45 |
+
Missing assignments, capacity overage, late delivery seconds, and unreachable
|
| 46 |
+
route legs.
|
| 47 |
+
- soft score
|
| 48 |
+
Total travel seconds.
|
| 49 |
+
- retained job
|
| 50 |
+
A solve that lives in memory so the UI can stream events, fetch snapshots,
|
| 51 |
+
pause/resume, cancel, analyze, and delete terminal jobs.
|
| 52 |
+
|
| 53 |
+
## Runtime Flow
|
| 54 |
+
|
| 55 |
+
1. The browser loads `static/index.html`.
|
| 56 |
+
2. `static/app/main.mjs` loads `static/sf-config.json`.
|
| 57 |
+
3. The app fetches `/demo-data/PHILADELPHIA`.
|
| 58 |
+
4. `PlanDto::from_plan()` serializes a refreshed transport plan with preview
|
| 59 |
+
state.
|
| 60 |
+
5. The browser normalizes the plan, renders summary cards, tables, timelines,
|
| 61 |
+
and a map.
|
| 62 |
+
6. When the user clicks Solve, the browser sends the current plan to
|
| 63 |
+
`POST /jobs`.
|
| 64 |
+
7. `src/api/routes.rs` deserializes the `PlanDto`, rebuilds a `Plan`, and calls
|
| 65 |
+
`prepare_plan()`.
|
| 66 |
+
8. `prepare_plan()` builds straight-line or road-network matrices and attaches
|
| 67 |
+
`PreparedVehicleRouting` to each vehicle.
|
| 68 |
+
9. `SolverService` starts a retained solve through `SolverManager<Plan>`.
|
| 69 |
+
10. Solver events are converted by `src/solver/service/runtime_payload.rs` into
|
| 70 |
+
UI-facing JSON.
|
| 71 |
+
11. The browser consumes `/jobs/{id}/events` and fetches snapshots, analysis,
|
| 72 |
+
and route geometry for exact snapshot revisions.
|
| 73 |
+
|
| 74 |
+
## File Map
|
| 75 |
+
|
| 76 |
+
```text
|
| 77 |
+
.
|
| 78 |
+
βββ Cargo.toml
|
| 79 |
+
β Rust 1.95 crate metadata for app version 1.0.0 and latest published
|
| 80 |
+
β crates.io dependencies.
|
| 81 |
+
βββ solver.toml
|
| 82 |
+
β Embedded search policy for construction heuristics and local search.
|
| 83 |
+
βββ solverforge.app.toml
|
| 84 |
+
β App metadata, demo IDs, model facts/entities, crates.io dependency sources,
|
| 85 |
+
β and the `solverforge 0.9.1` runtime target.
|
| 86 |
+
βββ Makefile
|
| 87 |
+
β Hospital-style local build, validation, and Space/Docker commands.
|
| 88 |
+
βββ Dockerfile
|
| 89 |
+
β Multi-stage Rust 1.95 Docker image for Hugging Face Spaces.
|
| 90 |
+
βββ .dockerignore
|
| 91 |
+
β Keeps build artifacts, git metadata, route cache, and Playwright output out
|
| 92 |
+
β of the Docker context.
|
| 93 |
+
βββ README.md
|
| 94 |
+
β Run guide, dependency shape, API list, and learning path.
|
| 95 |
+
βββ AGENTS.md
|
| 96 |
+
β Repo-specific rules for future edits.
|
| 97 |
+
βββ WIREFRAME.md
|
| 98 |
+
β This architectural walkthrough.
|
| 99 |
+
βββ src/
|
| 100 |
+
β βββ domain/
|
| 101 |
+
β β `planning_model!` manifest, `Plan`, entities, facts, preview structs,
|
| 102 |
+
β β and route metrics.
|
| 103 |
+
β βββ constraints/
|
| 104 |
+
β β Assignment, capacity, time-window, and travel-time score rules.
|
| 105 |
+
β βββ data/
|
| 106 |
+
β β Deterministic city seed data and generator entrypoints.
|
| 107 |
+
β βββ solver/
|
| 108 |
+
β β Retained-job service and runtime event payload formatting.
|
| 109 |
+
β βββ api/
|
| 110 |
+
β Axum routes, DTOs, and SSE endpoint.
|
| 111 |
+
βββ static/
|
| 112 |
+
β βββ index.html
|
| 113 |
+
β βββ sf-config.json
|
| 114 |
+
β βββ generated/ui-model.json
|
| 115 |
+
β βββ app/
|
| 116 |
+
β Browser controller, plan models, and UI renderers.
|
| 117 |
+
βββ tests/
|
| 118 |
+
βββ api_contract.rs
|
| 119 |
+
β Single integration-test crate composed from `tests/api_contract/*.rs`.
|
| 120 |
+
βββ api_contract/
|
| 121 |
+
β Catalog, job, lifecycle, SSE, and live-road modules.
|
| 122 |
+
βββ support/
|
| 123 |
+
β Shared integration-test helpers used by that single crate.
|
| 124 |
+
βββ e2e/
|
| 125 |
+
β Playwright browser tests for the served app.
|
| 126 |
+
βββ frontend_models.test.mjs
|
| 127 |
+
Frontend model tests.
|
| 128 |
+
```
|
| 129 |
+
|
| 130 |
+
## Domain And Route Metrics
|
| 131 |
+
|
| 132 |
+
`src/domain/plan.rs` stays small and macro-facing. It owns the `Plan` struct,
|
| 133 |
+
normalization, list shadow refresh, transport refresh, and the
|
| 134 |
+
`VrpSolution` implementation.
|
| 135 |
+
|
| 136 |
+
Route-specific behavior lives under `src/domain/route_metrics/`:
|
| 137 |
+
|
| 138 |
+
- `preparation.rs`
|
| 139 |
+
Builds matrices and per-vehicle prepared routing data.
|
| 140 |
+
- `cvrp_hooks.rs`
|
| 141 |
+
Supplies Clarke-Wright, k-opt, load, capacity, and route replacement hooks.
|
| 142 |
+
- `metrics.rs`
|
| 143 |
+
Computes per-vehicle route metrics.
|
| 144 |
+
- `scoring.rs`
|
| 145 |
+
Builds preview DTOs and aggregate hard/soft score components.
|
| 146 |
+
- `routes.rs`
|
| 147 |
+
Builds straight-line or encoded road-network route geometry snapshots.
|
| 148 |
+
- `insertions.rs`
|
| 149 |
+
Ranks candidate insertion positions for one delivery.
|
| 150 |
+
- `types.rs`
|
| 151 |
+
Shared route metrics, snapshots, candidates, and routing trait types.
|
| 152 |
+
|
| 153 |
+
This split keeps the public domain API stable while avoiding oversized files.
|
| 154 |
+
|
| 155 |
+
## Demo Data
|
| 156 |
+
|
| 157 |
+
`src/data/data_seed/entrypoints.rs` exposes three demo IDs:
|
| 158 |
+
|
| 159 |
+
- `PHILADELPHIA`
|
| 160 |
+
- `HARTFORD`
|
| 161 |
+
- `FIRENZE`
|
| 162 |
+
|
| 163 |
+
Each city has a small module with separate depot and grouped visit files. The
|
| 164 |
+
generator is deterministic. Every demo has ten vehicle depots, enough scaled
|
| 165 |
+
deliveries for those vehicles, reachable road-network coordinates, and enough
|
| 166 |
+
aggregate capacity before route ordering.
|
| 167 |
+
|
| 168 |
+
## API And Retained Runtime
|
| 169 |
+
|
| 170 |
+
The REST API handles job control and snapshot reads:
|
| 171 |
+
|
| 172 |
+
- `/jobs` creates a retained solver job.
|
| 173 |
+
- `/jobs/{id}` and `/jobs/{id}/status` expose summary state.
|
| 174 |
+
- `/jobs/{id}/snapshot` returns an exact or latest snapshot.
|
| 175 |
+
- `/jobs/{id}/analysis` runs constraint analysis for a snapshot.
|
| 176 |
+
- `/jobs/{id}/routes` returns route geometry for a snapshot.
|
| 177 |
+
- `/jobs/{id}/events` streams typed lifecycle events.
|
| 178 |
+
|
| 179 |
+
The insertion endpoint, `/recommendations/delivery-insertions`, is app-specific.
|
| 180 |
+
It prepares the submitted plan, removes the requested delivery from any
|
| 181 |
+
existing route, evaluates candidate insert positions, and returns preview plans.
|
| 182 |
+
|
| 183 |
+
## Frontend Layout
|
| 184 |
+
|
| 185 |
+
`static/app/main.mjs` is the controller. It owns current plan state, retained
|
| 186 |
+
job state, route identity tracking, and event handlers.
|
| 187 |
+
|
| 188 |
+
Supporting modules are split by responsibility:
|
| 189 |
+
|
| 190 |
+
- `static/app/models/core.mjs`
|
| 191 |
+
Clone and normalize incoming plans.
|
| 192 |
+
- `static/app/models/preview.mjs`
|
| 193 |
+
Draft straight-line preview scoring.
|
| 194 |
+
- `static/app/models/timeline.mjs`
|
| 195 |
+
Vehicle and delivery rail models.
|
| 196 |
+
- `static/app/models/formatters.mjs`
|
| 197 |
+
Labels, icons, tones, clocks, and durations.
|
| 198 |
+
- `static/app/ui/layout.mjs`
|
| 199 |
+
Page shell and stock SolverForge UI component composition.
|
| 200 |
+
- `static/app/ui/overview.mjs`
|
| 201 |
+
Summary, route list, non-panning route highlighting, map, and timeline
|
| 202 |
+
rendering.
|
| 203 |
+
- `static/app/ui/data-tables.mjs`
|
| 204 |
+
Read-only vehicle and delivery tables with delivery insertion recommendations.
|
| 205 |
+
- `static/app/ui/modals.mjs`
|
| 206 |
+
Analysis and insertion recommendation bodies.
|
| 207 |
+
- `static/app/ui/api-guide.mjs`
|
| 208 |
+
Visible API guide content.
|
| 209 |
+
- `static/app/ui/lifecycle.mjs`
|
| 210 |
+
Dataset markers and route-identity helpers.
|
| 211 |
+
|
| 212 |
+
## Validation Surfaces
|
| 213 |
+
|
| 214 |
+
Use the Makefile as the repo-local workflow:
|
| 215 |
+
|
| 216 |
+
- `make fmt-check`
|
| 217 |
+
- `make clippy`
|
| 218 |
+
- `make build-release`
|
| 219 |
+
- `make test`
|
| 220 |
+
- `make test-e2e`
|
| 221 |
+
- `make space-build`
|
| 222 |
+
- `make test-live-road`
|
| 223 |
+
- `make ci-local`
|
| 224 |
+
- `make pre-release`
|
| 225 |
+
|
| 226 |
+
`make ci-local` includes the Docker image build used by the Hugging Face Space.
|
| 227 |
+
|
| 228 |
+
The file-size rule is part of the architecture: keep files below 300 lines and
|
| 229 |
+
split by responsibility before they become broad catch-all modules.
|