technical
The Current SolverForge Architecture: CLI-First, Rust-Native, Explicit
SolverForge's current architecture is CLI-first without being opaque: one neutral project shell, generator-driven model growth, scalar and list planning variables, retained jobs, and explicit Rust code.
SolverForge is no longer primarily a collection of quickstarts, roadmap essays, or separate starter families. The current architecture is simpler and stricter:
cargo install solverforge-cli
solverforge new my-scheduler
cd my-scheduler
solverforge server
solverforge-cli is the default entry point. It creates one neutral application
shell, then grows that shell with generators and ordinary Rust edits. Fresh
projects carry scaffold target metadata from the installed CLI binary; run
solverforge --version to see the exact runtime, UI, and maps targets your
binary will generate.
That is the product shape to understand first.
The CLI Is The Front Door
The CLI owns project bootstrap and project maintenance:
solverforge newcreates a runnable app shell.solverforge generateadds domain facts, planning entities, planning variables, constraints, scores, solution types, demo data, and compound scaffold slices.solverforge destroyremoves generated resources from managed regions.solverforge serverruns the generated application locally.solverforge info,solverforge check,solverforge routes, andsolverforge testinspect and validate the project.solverforge configmanagessolver.toml.solverforge completionsemits shell completions.
The important part is what solverforge new does not ask.
It does not ask whether this is an employee scheduling app, a vehicle routing
app, a warehouse app, or a manufacturing app. It also does not expose starter
flags such as --scalar, --list, or --mixed.
The generated project starts neutral. The domain becomes concrete after scaffolding.
solverforge generate fact employee --field skill:String
solverforge generate entity shift --field starts_at:String --field ends_at:String
solverforge generate variable employee_idx \
--entity Shift \
--kind scalar \
--range employees \
--allows-unassigned
solverforge generate constraint no_overlap --pair --hard
solverforge generate data --size standard
That workflow is intentional. New projects should begin from a small runnable application, not from a copied demo that has to be deleted back into shape.
Scalar And List Are The Planning Shapes
Current SolverForge uses two public planning-variable families:
scalarfor a field that chooses one value from a range, optionally allowingNonewhen the domain permits unassigned work.listfor an ordered collection of elements, as in routing, sequencing, and list-assignment problems.
Those are the words the CLI accepts:
solverforge generate variable resource_idx --entity Task --kind scalar --range resources
solverforge generate variable stops --entity Route --kind list --elements visits
standard is not a variable kind. It can appear as a demo data size label, as
in solverforge generate data --size standard, but it is not the opposite of
list and it is not a current modeling term.
This matters because older SolverForge writing used different model-shape names
while the architecture was still moving. Current documentation should say
scalar, list, or mixed when it describes model shape.
The Generated App Is Explicit Rust
SolverForge uses generation to remove repetition, not to hide the application.
A generated project contains normal Rust modules for:
- domain types
- constraints
- demo data
- solver configuration
- HTTP routes
- retained solve jobs
- frontend metadata and static assets
The CLI maintains generated regions where it can safely update code. User-owned Rust stays visible. The generated app is not a black box and it is not a runtime DSL interpreter.
That design matches the solver core. SolverForge’s runtime is Rust-native and type-preserving. The hot paths stay compiled as concrete Rust code, while macros and generators provide the repetitive structure around domain metadata, constraint streams, value ranges, and app wiring.
The Runtime Is Retained
The current generated app is built around retained solve jobs rather than a single blocking request.
At the runtime layer, SolverManager owns jobs, snapshots, events, analysis,
and lifecycle control. At the generated-app layer, the scaffold exposes that as
ordinary application behavior:
- start a solve
- stream progress over SSE
- inspect the latest or historical snapshot
- analyze score breakdowns
- pause, resume, cancel, or delete a job
- keep the UI synchronized with typed solve events
In the current scaffold, that surface is visible as ordinary HTTP routes:
POST /jobs
GET /jobs/{id}
DELETE /jobs/{id}
GET /jobs/{id}/status
GET /jobs/{id}/snapshot
GET /jobs/{id}/analysis
POST /jobs/{id}/pause
POST /jobs/{id}/resume
POST /jobs/{id}/cancel
GET /jobs/{id}/events
This is the current shape of SolverForge as an application framework. The CLI
does not just create a Rust library crate with a main.rs; it creates a
running service boundary around the retained solver lifecycle.
The UI Is Shipped Infrastructure, Not A Copied Demo
Older quickstart repositories carried their own frontend code because examples were the primary onboarding surface. Current CLI-generated apps instead compose the shipped SolverForge frontend assets and metadata contract.
That keeps generic UI behavior in solverforge-ui and keeps generated projects
focused on the planning domain. The app still has concrete files, routes, and
static assets, but it does not vendor a separate tutorial frontend stack as the
starting point for every user.
The result is a clearer division of ownership:
- SolverForge owns reusable runtime, UI, and generator machinery.
- The generated app owns domain code and project configuration.
- The developer owns the planning model, constraints, data shape, and solver tuning.
Quickstarts Are References, Not The Default Start
Worked examples still matter. A complete scheduling or routing example is useful when you want to study modeling patterns, constraint structure, or UI behavior in a real domain.
But quickstarts are no longer the default starting point for a new project. The default start is:
solverforge new my-project
Then generators and Rust edits shape the app. Tutorials and examples sit beside that workflow as references.
This distinction prevents a common onboarding failure: cloning an example, deleting most of it, and trying to guess which files were essential framework structure and which files were only demo residue.
What Older Articles May Get Wrong
Some older SolverForge articles are still useful as historical context, but they should not be read as the current architecture.
If an article says the CLI is only a later direction, that is stale. The CLI is the default entry point.
If an article says users choose a problem class or starter family up front, that
is stale. solverforge new creates one neutral shell.
If an article uses an older non-list model-shape name, that is stale. The
current term is scalar.
If an article frames SolverForge mainly as broad positioning, read that as old positioning, not as the product contract. The current contract is more concrete: a Rust-native solver runtime plus a CLI that creates and maintains explicit SolverForge applications.
The Current Mental Model
The shortest accurate description is this:
SolverForge is a Rust constraint-solving runtime with a CLI-first application workflow. The CLI creates one neutral app shell. Generators add scalar and list planning models. The generated service exposes retained solve jobs, SSE progress, snapshots, analysis, and UI integration. The code remains explicit Rust.
That is the architecture users should start from now.