File size: 8,056 Bytes
53664d2
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
---
title: SolverForge Furnace
emoji: 🔥
colorFrom: orange
colorTo: red
sdk: docker
app_port: 7860
pinned: false
license: apache-2.0
short_description: SolverForge heat-treatment furnace scheduling example
---

# SolverForge Furnace

![SolverForge Furnace screenshot](docs/screenshot.png)

`solverforge-furnace` is a SolverForge heat-treatment scheduling app with
retained jobs, a furnace schedule timeline, operator roster views, and a
browser workspace built on the shared `solverforge-ui` shell.

It answers one concrete question:

"Given furnaces, work orders, task operators, and a weekly shift roster, when
should each order run, on which furnace, and which operator performs each
manual task?"

## Quick Start

```sh
make run-release
```

Then open `http://localhost:7860`.

To inspect the supported command surface:

```sh
make help
```

## Documentation Map

- `README.md`
  Quick start, model concepts, validation, REST API, and solver policy.
- `WIREFRAME.md`
  As-built architecture and runtime/data flow across backend, runtime, and UI.
- `AGENTS.md`
  Codex-facing maintenance, validation, and documentation rules.
- `Makefile`
  Supported local commands for development, validation, Docker, and Space work.
- `Dockerfile`
  Docker Space image build using Rust 1.95 and the declared crates.io line.

## Current Dependency Shape

- Package: `solverforge-furnace`; version is declared in `Cargo.toml`
- Release binary: `solverforge-furnace`
- Rust: `1.95`
- SolverForge runtime: `solverforge` `0.19.4`
- Browser UI assets: `solverforge-ui` `0.6.5`
- Scaffold metadata: `solverforge-cli` `2.2.2` in `solverforge.app.toml`

The app serves registry-backed Rust dependencies, local static browser modules,
and Axum API routes from one process.

## Model Concepts

- `Furnace`, `WorkOrder`, `Operator`, `Shift`, and `ShiftCoverageDemand` are
  problem facts: input data the solver reads but does not move.
- `FurnaceAssignment` is a planning entity: one batch decision per work order.
  Its `assignment` variable combines the target furnace and 15-minute start slot
  into a single scalar value, and its four task variables pick the operator for
  load/build, program, quench, and unload.
- `OperatorShiftAssignment` is a planning entity: one row per operator and
  roster day. Its `shift_type` variable chooses Morning, Afternoon, Night, or
  Off.
- `Plan` is the planning solution with the current `HardSoftScore`.

Time is measured in minutes since Monday 00:00 over a seven-day horizon with a
15-minute time step. A batch always moves through a heating ramp followed by a
soak. Around each batch the app books four manual tasks relative to the batch
start and end: load/build, program, quench when the process requires it, and
unload.

The app ships one deterministic `STANDARD` dataset with 11 furnaces, 155 work
orders, 39 operators, 22 shifts, and 44 coverage demands. It starts with every
order and operator unassigned, so the timeline is empty until the solver runs.

## Constraints

Hard constraints:

- Every work order must be scheduled.
- A furnace must support the order process, temperature, and load.
- A batch must finish inside the seven-day horizon.
- Batches on the same furnace cannot overlap and must respect the thermal
  changeover gap.
- Each manual task window must be owned by a single shift.
- Assigned tasks require a scheduled batch.
- Every required manual task must receive an operator.
- The operator must have the task's skill and be rostered on the owning shift.
- An operator cannot be double-booked across overlapping task windows.
- Each `(shift, role)` coverage demand must be staffed.
- Monitoring capacity must cover ramp, soak, and task load in every 15-minute
  bucket.
- Day-only operators cannot work nights.
- Consecutive days must respect minimum rest.
- Operators cannot exceed the weekly visible-shift and consecutive-night limits.

Soft constraints:

- Express, Urgent, and Standard orders are penalized by lateness with
  priority-weighted cost.
- Thermal changeover cost is minimized.
- Early finishing above the due time is mildly penalized.
- Night starts for non-carburizing/non-nitriding work are discouraged.
- Overtime above the target weekly shift count is penalized.
- Working shifts are balanced across operators.

## REST API

- `GET /health`
- `GET /info`
- `GET /demo-data`
- `GET /demo-data/{id}`
- `POST /jobs`
- `GET /jobs/{id}`
- `DELETE /jobs/{id}`
- `GET /jobs/{id}/status`
- `GET /jobs/{id}/snapshot`
- `GET /jobs/{id}/analysis`
- `GET /jobs/{id}/analysis/{constraint_name}`
- `POST /jobs/{id}/pause`
- `POST /jobs/{id}/resume`
- `POST /jobs/{id}/cancel`
- `GET /jobs/{id}/events`

`snapshot_revision={n}` is optional for snapshots and analysis. SSE clients
receive a bootstrap event and then live retained-job events.

## Solver Policy

`solver.toml` is embedded by `Plan` and is the runtime source of truth.

- `random_seed = 42` keeps the demo reproducible.
- Three grouped construction phases assign furnace slots
  (`weakest_fit_decreasing`), the operator roster (`cheapest_insertion`), and
  task operators (`weakest_fit`), each with
  `construction_obligation = "assign_when_candidate_exists"`.
- A variable-neighborhood-descent local search performs hard repair with
  compound conflict-repair and grouped-scalar selectors.
- A simulated-annealing polish phase uses `decay_rate = 0.999985`,
  `hard_regression_policy = "never_accept_hard_regression"`, and an
  `accepted_count` forager with `limit = 256`.
- Solving stops after 45 seconds, or after 12 seconds without improvement.

The slow acceptance test expects solving to reach hard feasibility from the
fully unassigned public instance while soft penalties continue to represent
schedule quality.

## Validation

Standard validation:

```sh
make test
```

Full local validation:

```sh
make ci-local
```

Slow acceptance solve:

```sh
make test-slow
```

`make test` runs Rust tests, frontend syntax checks, and a Playwright browser
smoke. `make ci-local` adds formatting, clippy, release build, and Docker image
build. `make pre-release` runs `ci-local` plus the slow acceptance solve.

## Hugging Face Space Deployment

This repo is Docker-Space ready. The Space 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
```

## Read The Code In This Order

1. `src/domain/mod.rs`
   The `planning_model!` manifest and public domain exports.
2. `src/domain/plan.rs`
   The `Plan` solution, fact collections, and entity collections.
3. `src/domain/resources.rs`
   `Furnace`, `WorkOrder`, `Operator`, `Shift`, and `ShiftCoverageDemand`.
4. `src/domain/furnace.rs` and `src/domain/coverage.rs`
   The two planning entities and their derived task/roster helpers.
5. `src/constraints/mod.rs` and `src/constraints/*.rs`
   The score model, one rule group per file.
6. `src/data/data_seed/`
   The deterministic `STANDARD` demo generator.
7. `src/solver/service.rs`
   Retained-job orchestration over `SolverManager<Plan>`.
8. `src/solver/scalar_groups.rs` and `src/solver/conflict_repair.rs`
   The grouped scalar providers and conflict-directed repair providers that
   `solver.toml` refers to by name.
9. `src/api/routes/` and `src/api/dto/`
   HTTP routes, transport DTOs, and live-event streaming.
10. `static/app/runtime.js` and `static/app/schedule.js`
    Browser boot sequence, solver controls, and furnace timeline rendering.

## Project Shape

- `src/domain/`
  Planning model, domain types, planning variables, and derived indexes.
- `src/constraints/`
  Incremental SolverForge scoring rules.
- `src/data/`
  Deterministic heat-treatment demo-data generator.
- `src/solver/`
  Retained-job facade, scalar-group providers, conflict-repair providers, and
  runtime event payload formatting.
- `src/api/`
  Axum routes, DTOs, and SSE endpoint.
- `static/`
  Browser workspace built on stock `solverforge-ui` assets.
- `Makefile`
  Contains the inline `test-e2e` Playwright smoke for the served app.