# SolverForge Upstream Feature Audit
Audit date: 2026-07-29
This audit compares the current `solverforge-cli` scaffold surface against the
live SolverForge upstream checkout at `/srv/lab/dev/solverforge/solverforge`
and the crates.io release state. Generated projects now target the published
SolverForge `0.19.3` release. Registry-only generated-app validation is the
release gate; `SF_USE_LOCAL_PATCHES=1` remains reserved for explicit future
prerelease checks against sibling checkouts.
The inclusion bar is starter-safe only: a feature is worth adding to the CLI
when it helps generated projects express a current SolverForge capability
without turning the neutral scaffold into a domain-specific demo.
## Source Evidence
- Published gate: `cargo info solverforge@0.19.3` resolves the published crate
on 2026-07-29, with Rust `1.95` and the scaffolded `serde`,
`console`, and `verbose-logging` feature set still available.
- Upstream local checkout: the workspace and inter-crate dependency baseline is
`0.19.3`, with `v0.19.3` at the checked-out release commit. The `0.19.0`
release made list variables the sole sequence and route model; the published
`0.19.1` through `0.19.3` patch line carries the subsequent solver fixes.
- Previous upstream releases: `solverforge/CHANGELOG.md` lists `0.17.2`
dynamic construction primitives and required-assignment streaming, `0.17.0`
CVRP list-domain profile support, and `0.16.0` split route/savings hooks.
- Earlier upstream release: `solverforge/CHANGELOG.md` lists `0.15.2` directed
projected self-join scoring work.
- Earlier upstream release: `solverforge/CHANGELOG.md` lists `0.15.1`
features for the bridge crate, dynamic runtime slots, list precedence hooks,
fixed-owner list handling, and mandatory list construction.
- Previous upstream release: `solverforge/CHANGELOG.md` lists `0.15.0`
features for typed shared constraint sets, shared grouped-node state,
assignment value-pattern neighborhoods, and required scalar assignment
construction.
- Upstream release: `solverforge/CHANGELOG.md` lists `0.14.1` and `0.14.0`
features for shared route metric classes, owner-aware route hooks,
complemented direct cross-join groups, and filtered join preservation.
- Earlier upstream release: `solverforge/CHANGELOG.md` lists features for
generalized grouped collectors and a scoring fix that preserves joined filter
source indexes.
- Upstream release: `solverforge/CHANGELOG.md` lists `0.13.0` features for
typed model-aware search defaults, streaming-first stock search, grouped
assignment ownership/search tuning, bounded grouped scalar and conflict repair
streams, explicit score weight wrappers, and collector additions.
- Upstream release: `solverforge/CHANGELOG.md` lists a `0.13.0` breaking
scoring change: constraint streams removed `penalize_with`, `reward_with`,
and the hard/soft shortcut variants in favor of `penalize(score)`,
`reward(score)`, and typed dynamic scoring closures.
- Upstream release: `solverforge/CHANGELOG.md` lists `0.12.1` features for
folding the former coverage behavior into scalar assignment groups and
unifying assignment-backed grouped scalar construction.
- Upstream release: `solverforge/CHANGELOG.md` lists `0.12.0` features for
declarative scalar planning contracts, scalar/grouped construction and repair
configuration, model-owned grouped scalar declarations, consecutive-run
scoring collectors, and the cleaned public constraint stream surface.
- Upstream domain docs: `docs/extend-domain.md` documents scalar candidate,
nearby, distance-meter, and construction-order hooks on
`#[planning_variable]`.
- Upstream solver docs: `docs/extend-solver.md` documents capability-routed
construction, `group_name` routing into `ScalarGroup`, canonical selector
defaults, grouped assignment construction, grouped scalar local search, and
scalar candidate limits.
- Upstream config docs: `crates/solverforge-config/WIREFRAME.md` documents
`group_name`, `construction_obligation`, grouped-scalar construction limits,
and `grouped_scalar_move_selector`.
- Upstream macro docs: `crates/solverforge-macros/WIREFRAME.md` documents
`scalar_groups = "path"` on `#[planning_solution]` and scalar hook arguments
on `#[planning_variable]`.
- Upstream example: `examples/minimal-shift-scheduling` demonstrates
`scalar_groups`, `ScalarGroup::assignment`, grouped scalar construction with
`group_name`, `construction_obligation = "assign_when_candidate_exists"`, and
`grouped_scalar_move_selector`.
- CLI coverage today: the scaffold targets `solverforge 0.19.3` and includes
the retained `SolverManager` lifecycle, typed SSE, snapshots, analysis,
pause/resume/cancel/delete, generated `solverforge.app.toml`, scalar/list
variable generation, complete executable scalar/list metadata projection,
countable scalar ranges, full compact telemetry, bounded candidate-detail
retrieval, and qualified trace jobs.
- Mixed execution gate: fresh runtime and browser scenarios seed a required
scalar variable plus a list variable, start a retained solve, verify scalar
assignment and complete list placement, and exercise cancel/terminal cleanup.
- UI release gate: `cargo info solverforge-ui` confirms `solverforge-ui 0.7.0`
is published; the web scaffold targets its framework-neutral asset release.
- Local checkout note: `/srv/lab/dev/solverforge/solverforge` remains the
source gate used to inspect the current release notes and feature surface.
## Inclusion Matrix
| Upstream feature | Current CLI coverage | Starter-safe verdict | Proposed CLI/scaffold change | Required tests |
| --- | --- | --- | --- | --- |
| `scalar_groups = "path"` on `#[planning_solution]` | Implemented as an opt-in solution attribute and app-spec/UI projection surface through `solverforge generate scalar-group`. | Included, opt-in only. It is the current model-owned grouped scalar entry point, but it must not appear in the neutral default. | Keep the neutral scaffold unchanged. The command updates the planning solution attribute with `scalar_groups = "scalar_groups"` and owns a clear domain hook seam. | Unit tests for solution-attribute parsing/rewrite and rendered group declarations; scaffold coverage should remain neutral by default. |
| Assignment-backed `ScalarGroup::assignment` | Implemented as `solverforge generate scalar-group NAME --assignment Entity.field` with explicit hook flags and limits. | Included. This remains the replacement for the older coverage-group concept and is generic enough for opt-in scaffolding. | The command requires an existing nullable scalar variable target and generates only metadata/wiring plus hook stubs that panic until the user supplies domain logic. | Parser/generator tests; generated-app `cargo check` after user-owned hook bodies are present; negative tests that neutral scaffolds do not emit scalar groups. |
| Candidate-backed `ScalarGroup` | Implemented as `solverforge generate scalar-group NAME --candidates provider --target Entity.field [...]`. | Included, opt-in only. It is too domain-specific for defaults but valuable as a CLI-owned wiring surface. | The command validates existing scalar targets, wires the candidate provider path, emits an explicit provider stub for local function names, and generates grouped construction plus search config unless `--skip-solver-config` is passed. | Unit tests for target rendering and config refs; generated-app `cargo check` after provider implementation exists. |
| Grouped scalar construction through `group_name` | Implemented as generated `solver.toml` phases for assignment-backed and candidate-backed scalar groups unless `--skip-solver-config` is passed. | Included only after a scalar group exists. Do not change default `solver.toml`. | The command inserts a construction phase with `group_name`, limits, and `construction_obligation = "assign_when_candidate_exists"` for both assignment and candidate groups. | Config graph tests; generated app `solverforge check`; generated app `cargo check`; runtime smoke only if the command claims solve behavior. |
| `grouped_scalar_move_selector` | Implemented as a generated local-search move selector for scalar groups unless `--skip-solver-config` is passed. | Included only after a scalar group exists. Do not add to neutral local-search defaults. | The command inserts grouped local-search config with `group_name`, `max_moves_per_step`, optional `value_candidate_limit`, and `require_hard_improvement`. | Config generation tests and generated app `cargo check`; runtime pipeline if used in an end-to-end generated scenario. |
| `construction_obligation = "assign_when_candidate_exists"` | Implemented as part of generated assignment-backed and candidate-backed scalar-group construction phases. It is not exposed as a standalone config flag. | Include only as part of scalar-group config, not as a neutral scaffold default. | Keep this tied to `generate scalar-group`; do not add it to neutral `solver.toml` or generic `config set` presets. | TOML assertions and generated app compile checks. |
| Scalar `candidate_values` hook | Implemented in this worktree: `generate variable --kind scalar` accepts `--candidate-values`, renders it into `#[planning_variable(...)]`, parses handwritten attributes, persists it in `solverforge.app.toml`, and projects it into `static/generated/ui-model.json`. | Covered. This is a generic scalar modeling capability and remains starter-safe as metadata only. | No further scaffold change. Keep hook bodies domain-owned and keep tests proving generated apps compile when the user provides the hook. | Existing parser/generator/app-spec/scaffold tests. |
| Scalar nearby hooks and distance meters | Implemented in this worktree for `--nearby-value-candidates`, `--nearby-entity-candidates`, `--nearby-value-distance-meter`, and `--nearby-entity-distance-meter`. | Covered. Nearby selectors remain opt-in because the model must bound candidate discovery explicitly. | No further scaffold change. Do not alter `solver.toml` defaults when these flags are present. | Existing parser/projection/generation/scaffold tests; keep coverage that no nearby selector is emitted by default. |
| Scalar construction order hooks | Implemented in this worktree for `--construction-entity-order-key` and `--construction-value-order-key`. | Covered. Required by scalar-only order-sensitive construction heuristics, but metadata alone should not switch solver policy. | No further scaffold change. A future config preset can validate that required hooks exist before selecting order-sensitive construction. | Existing parser/projection/generated-attribute tests. |
| Countable scalar value ranges | Implemented as mutually exclusive `--countable-range FROM..TO`, with non-negative half-open validation, macro emission, domain parsing, app-spec/UI projection, numeric web rendering, and a fresh generated-app compile check. | Covered. This is a canonical scalar value source and does not require a synthetic fact collection. | Keep the stored macro/app-spec form as `from..to`; keep the UI projection structured as numeric `from`/`to` bounds. | Parser/validation unit tests, projection assertions, and generated-app `cargo check` against 0.19.3. |
| Sequence and route modeling | Implemented only through `--kind list --elements <collection>` and current list metadata. | Included. One list representation owns assignment and order and is the canonical sequence architecture. | Keep the public CLI, app spec, parser, generated data, UI projection, and runtime gates scalar/list-only. | List generator/parser/projection tests, mixed generated-app compile and runtime gates, and route-profile coverage. |
| Current construction heuristic catalog | CLI ships conservative scalar/list template defaults and generic `config set`. | Do not mirror every variant in scaffold defaults. | Document which upstream heuristics need opt-in model hooks; keep `first_fit` and `list_cheapest_insertion` templates stable until a command explicitly owns a configured preset. | Docs/audit assertions only unless a preset command is added. |
| Immutable runtime compilation and resolved selector policy | Generated planning macros and `solver.toml` enter the canonical 0.19.3 runtime compiler; the templates do not assemble phases directly. | Covered by the runtime dependency upgrade. This is runtime-owned architecture, not a new scaffold family or compatibility path. | Keep the generated model and config contracts unchanged and validate every shell plus scalar, list, and mixed runtime pipelines against 0.19.3. | Registry-only scaffold checks, seeded scalar/mixed generated solves, and browser lifecycle tests. |
| Qualified candidate execution traces | Implemented as an opt-in config setting, complete typed diagnostic DTO, `GET /jobs/{id}/telemetry`, and additive `POST /jobs/qualified` entry point carrying all required external digests and producer attestation. Candidate pulls remain absent from ordinary SSE/status/snapshot payloads. | Included but disabled by default. This preserves the runtime's compact control plane while exposing the complete diagnostic and qualification surface. | Keep the commented `[candidate_trace]` example, positive-capacity validation, separate detail route, and qualified provenance request aligned with the runtime types. | Unit config validation, scaffold source assertions, fresh generated-app compile checks, and a runtime pipeline that proves normal and qualified retained traces. |
| CVRP list profile and split route/savings hooks | Implemented through `generate variable --kind list`: `--domain cvrp` plus all generic distance, route/savings, metric-class, ownership, construction-order, precedence, and solution-trait metadata. Domain parsing, app spec, and web UI projection preserve the exact values. | Included as opt-in metadata; the neutral scaffold remains domain-free. The CLI rejects profile-owned overrides alongside `--domain cvrp`. | Keep hook bodies and CVRP trait implementation domain-owned. Do not inject fake route logic or a domain-specific default model. | Generator/parser tests, app-spec/UI projection coverage, CVRP conflict validation, upstream macro tests, and generated-app checks for the neutral/list templates. |
| Canonical local-search defaults | CLI templates still specify explicit late-acceptance plus accepted-count local search. | No immediate change. Explicit scaffold defaults are stable and compile; upstream omitted-selector defaults are runtime-owned. | Leave current `solver.toml` templates alone. Consider a later docs note that deleting `move_selector` lets runtime choose canonical defaults. | Existing scaffold/runtime tests. |
| Scoring collectors and grouped/complemented stream APIs, including `consecutive_runs`, `indexed_presence`, and `collect_vec` | Implemented as opt-in advanced constraint skeleton flags while leaving scoring logic to the app. | Include as skeletons only. These APIs are important, but generated neutral constraints should not choose domain-specific collectors. | Keep the skeletons on the public stream surface with explicit panic placeholders. | Existing constraint-generation tests plus focused skeleton assertions. |
| Conflict repair providers via `conflict_repairs = "path"` | Implemented as `solverforge generate conflict-repair CONSTRAINT_ID --provider provider_fn` with optional selector config. | Included, opt-in only. It requires constraint-specific provider code and is not neutral starter behavior. | The command wires `conflict_repairs = "conflict_repairs"`, emits a provider stub for local function names, and stores the exact snake_case constraint ID in generated Rust, app metadata, and solver config. | Unit tests for rendering and config mutation; generated-app `cargo check` after provider implementation exists. |
| Retained `SolverManager` lifecycle | Already represented in templates, routes, DTOs, JS hooks, runtime tests, and E2E tests. | Already covered. | No action. Keep scaffold assertions protecting snapshots, lifecycle metadata, and pause/resume/cancel/delete semantics. | Existing scaffold, runtime, and Playwright lifecycle tests. |
| Clean public stream surface | CLI-generated constraints already use `ConstraintFactory::new().for_each(Plan::...)` and do not teach generated helper-trait imports. | Already covered. | No action beyond keeping examples/docs on public SolverForge API only. | Existing constraint-generation compile tests. |
## Recommended Follow-Up Implementation Slice
The current starter-safe 0.19.3 surface is implemented. The next high-value slice
is domain-specific documentation and executable examples, not more neutral
scaffold defaults.
1. Keep `solverforge new` neutral and continue treating scalar groups and
conflict repairs as explicit post-scaffold modeling choices.
2. Add human-facing examples for list profiles, scalar groups, conflict repair,
and qualified diagnostics only with real hook bodies and real provenance.
3. Prove any runtime behavior claims with generated apps whose hook bodies are
real Rust, not TODO stubs.
## Implementation Status
- Release state: `solverforge 0.19.3` is published on crates.io and matches both
the live upstream release checkout and this generated target. Registry-only
validation is therefore authoritative. `SF_USE_LOCAL_PATCHES=1` is only for
an explicit future coordinated prerelease check. The audit uses the current
`scalar_groups` / `ScalarGroup::assignment` vocabulary instead of the
superseded coverage-group vocabulary from the earlier 0.12.0 candidate
surface.
- Implemented: scalar fact-collection and countable value sources plus
`candidate_values`, nearby candidate hooks, nearby distance meters, and
construction order keys are accepted by
`solverforge generate variable --kind scalar`, rendered into the
`#[planning_variable(...)]` attribute, parsed from handwritten domain files,
persisted in `solverforge.app.toml`, and projected into
`static/generated/ui-model.json`.
- Aligned: ordered sequence and route modeling uses list variables end to end.
The public CLI, canonical parser, app spec, generated data, UI projection,
checks, and runtime scenarios contain only scalar and list variable contracts.
- Implemented: list `domain`, distance meters, split route/savings hooks,
savings metric class, fixed ownership, construction ordering, precedence
hooks, and solution-trait metadata across CLI generation, canonical parsing,
app-spec persistence, and web UI projection. The stock CVRP profile is
accepted without allowing conflicting profile-owned overrides.
- Implemented: every compact `SolverTelemetry` field and nested
phase/selector/move/applied-move breakdown is projected into generated
status, snapshot, and SSE payloads. Bounded candidate pulls use the separate
atomic detail accessor and typed diagnostic DTO.
- Implemented: candidate tracing is configurable through
`candidate_trace.max_entries` with positive-capacity validation. Generated
web/API apps expose ordinary trace detail and explicitly qualified trace jobs
with the five immutable external SHA-256 digests required by the current
runtime contract.
- Implemented: opt-in scalar groups through `solverforge generate scalar-group`
for assignment-backed and candidate-backed groups, including solution
attribute wiring, app-spec/UI metadata, local hook stubs, solver config phase
insertion inside a single CLI-managed `solver.toml` region, and destroy
cleanup.
- Implemented: `solver.toml` validation now treats scalar groups and conflict
repairs as exact-ID graph references. `solverforge check` and destroy
planning inspect construction phases, top-level selectors, neighborhoods,
nested selector children, and partition child phases instead of scanning only
flat top-level TOML. This is implemented inside `solverforge-cli`; no
unpublished upstream `solverforge-config` API is required.
- Implemented: scalar-group model-contract validation is shared by
`solverforge check` and destructive commands. Candidate-backed groups reject
assignment-only hooks, assignment rules require sequence keys, stale
scalar-group targets are reported, solver config group references are checked,
and `destroy entity` / `destroy variable` reject targets that are still owned
by scalar groups.
- Implemented: opt-in conflict repairs through
`solverforge generate conflict-repair`, including solution attribute wiring,
app-spec/UI metadata, local provider stubs, solver config phase insertion,
and destroy cleanup.
- Implemented: `solverforge config set` performs lossless non-phase TOML edits
such as `termination.seconds_spent_limit`; ordered `phases` are edited
manually or by future phase-specific commands, not by dotted-key mutation.
- Implemented: advanced public collector skeletons for consecutive runs,
indexed presence, collected vectors, grouped complement, and projected
grouped constraints.
- Hardened: advanced grouped constraint skeletons use named source helpers and
typed scoring closures instead of unsupported post-group filters, and fresh
generated apps now compile before users replace the TODO predicates.
- Aligned: the list scaffold's built-in soft constraints use the current
typed dynamic `penalize(|item| Score::...)` scoring API instead of the removed
`penalize_with` helper.
- Preserved: the CLI still does not generate real Rust hook bodies. Generated
stubs fail fast with TODO panics until the user-owned hook functions are
implemented.
- Preserved: neutral `solver.toml` policy is unchanged. Its commented candidate
trace block documents the opt-in without enabling diagnostic overhead.
Scalar/list metadata flags do not select unrelated heuristics automatically.
- Not implemented by design: neutral scalar-group, conflict-repair, or grouped
solver defaults. These remain opt-in modeling resources.
## Non-Goals
- Do not add `minimal-shift-scheduling` or any domain-specific demo to
`solverforge new`.
- Do not make grouped scalar construction or `grouped_scalar_move_selector` the
neutral default.
- Do not generate hook functions that silently return fake business logic.
Generated local stubs must panic until the user supplies real logic.
- Do not reintroduce scaffold-family aliases, legacy variable kinds, or
compatibility rewrites for old generated project shapes.
- Do not add scalar predecessor topology; ordered sequences and routes belong to
list variables.
## Validation Gate For Future Code Changes
Any implementation from this audit should pass:
- focused parser/generator/app-spec tests for the new metadata;
- scaffold contract tests proving fresh generated projects include only the
opt-in scalar-group surface requested by the user;
- generated app `cargo check` against the published `0.19.3` registry target;
- runtime pipeline coverage only if the new command claims actual solving
behavior;
- `SF_USE_LOCAL_PATCHES=1` only for an explicit future sibling-checkout
compatibility check, followed by the same registry-only gate once that target
is published.