You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
-`variant_params!` macro implements `Problem::variant()` — e.g., `crate::variant_params![G, W]` for two type params, `crate::variant_params![]` for none (see `src/variant.rs`)
154
-
-`declare_variants!` proc macro registers concrete type instantiations with best-known complexity and registry-backed load/serialize/value-solve/witness-solve metadata. One entry per problem may be marked `default`, and variable names in complexity strings are validated at compile time against actual getter methods.
154
+
-`declare_variants!` proc macro registers concrete type instantiations with best-known complexity and registry-backed load/serialize/value-solve/witness-solve metadata. One entry per problem may be marked `default`, and variable names in complexity strings are validated at compile time against actual getter methods. Ordinary models are constructed directly from their construction schema. When user-facing construction differs from persisted JSON, define a model-local `#[derive(CreateSpec)]` DTO plus `TryFrom<CreateSpec>`, use its generated `FIELDS` in `ProblemSchemaEntry`, and register it with `create LocalSpec`; never add model-name branches in CLI or MCP code.
155
155
-`decision_problem_meta!` macro registers `DecisionProblemMeta` for a concrete inner type, providing the `DECISION_NAME` constant.
156
156
-`register_decision_variant!` macro generates `declare_variants!`, `ProblemSchemaEntry`, and both `ReductionEntry` submissions (aggregate Decision→Opt + Turing Opt→Decision) for a `Decision<P>` variant. Callers must define inherent getters (`num_vertices()`, `num_edges()`, `k()`) on `Decision<P>` before invoking. Accepts `dims`, `fields`, and `size_getters` parameters for problem-specific size fields.
157
157
- Problems parameterized by graph type `G` and optionally weight type `W` (problem-dependent)
@@ -204,9 +204,9 @@ Reduction graph nodes use variant key-value pairs from `Problem::variant()`:
204
204
205
205
### Extension Points
206
206
- New models register dynamic load/serialize/brute-force dispatch through `declare_variants!` in the model file, not by adding manual match arms in the CLI
207
-
-**CLI creation is schema-driven and deferred:**`pred create`builds lightweight problem/variant command shells, then expands fields only for the selected command. Construction fields are classified as external, derived, or composite; both Clap and the builder consume that classification. Ordinary external fields come from `ProblemSchemaEntry`, derived fields are not exposed as flags, and composite graph fields expand through the existing construction semantics (for example `BipartiteGraph` uses `--left`, `--right`, and `--biedges`). New models do not add fields to a central Clap struct. Add parser support only when introducing a genuinely new field representation.
208
-
-**Each CLI input has one name.** Do not add compatibility aliases or multi-name lookup. Schema fields normally use `snake_case → kebab-case`; a composite or derived input may use the single construction name returned by `problem_help_flag_name()`.
209
-
-**Decision variants** of optimization problems use `Decision<P>` wrapper. Add via: (1) `decision_problem_meta!` for the inner type, (2) inherent methods on `Decision<Inner>`, (3) `register_decision_variant!` with `dims`, `fields`, `size_getters`. Schema-driven CLI creation auto-restructures flat JSON into`{inner: {...}, bound}`.
207
+
-**CLI creation is registry-driven and deferred:**`pred create` expands flags only for the selected concrete variant. Ordinary models use `ProblemSchemaEntry.fields` directly. Models whose construction differs from persisted JSON own a typed `CreateSpec`and fallible conversion beside the model; CLI and MCP only normalize transport values and invoke the registered constructor.
208
+
-**Each construction input has one name and one concrete type per variant.** Do not add compatibility aliases or infer types from flag names. `CreateSpec` field names render as `snake_case → kebab-case` in CLI and remain `snake_case` in MCP. Add a reusable codec only for a genuinely new transport representation, never a model-name parser branch.
209
+
-**Decision variants** of optimization problems use `Decision<P>` wrapper. Add via: (1) `decision_problem_meta!` for the inner type, (2) inherent methods on `Decision<Inner>`, (3) `register_decision_variant!` with `dims`, `fields`, `size_getters`. The generated construction spec accepts flat inner fields plus `bound`; persisted JSON remains`{inner: {...}, bound}`.
210
210
- Aggregate-only models are first-class in `declare_variants!`; aggregate-only and Turing reduction edges still need manual `ReductionEntry` wiring because `#[reduction]` only registers witness/config reductions today
211
211
- Exact registry dispatch lives in `src/registry/`; alias resolution and partial/default variant resolution live in `problemreductions-cli/src/problem_name.rs`
212
212
-`pred create` schema-driven dispatch lives in `problemreductions-cli/src/commands/create.rs` (`create_schema_driven()`)
-**CLI and MCP construction:** discovered from the model's registry entry; no frontend model-name dispatch
73
72
-**Canonical model examples:**`src/example_db/model_builders.rs`
74
73
75
74
## Pre-review Checklist
76
75
77
76
Before implementing, make sure the plan explicitly covers these items that structural review checks later:
78
77
- Derive numeric implementation types from the mathematical domains in the issue and follow `docs/src/design.md#numeric-types-and-arithmetic`; serde/CLI construction uses the same validation as `new`/`try_new`, and boundary tests cover the supported maximum without requiring impractical allocation
79
-
-`ProblemSchemaEntry` metadata is complete for the current schema shape (`display_name`, `aliases`, `dimensions`, and constructor-facing`fields`)
78
+
-`ProblemSchemaEntry` metadata is complete for the construction interface (`display_name`, `aliases`, `dimensions`, and `fields`)
80
79
-`Problem::Value` uses the correct aggregate wrapper and witness support is intentional
81
80
-`declare_variants!` is present with exactly one `default` variant when multiple concrete variants exist
82
81
- CLI discovery and `pred create <ProblemName>` support are included where applicable
-**Schema metadata:**`ProblemSchemaEntry` must reflect the current registry schema shape, including `display_name`, `aliases`, `dimensions`, and constructor-facing`fields`
125
+
-**Schema metadata:**`ProblemSchemaEntry` must reflect the construction interface, including `display_name`, `aliases`, `dimensions`, and `fields`
127
126
-**Objective problems:** use `type Value = Max<_>`, `Min<_>`, or `Extremum<_>` when the model should expose optimization-style witness helpers
128
127
-**Witness problems:** use `type Value = Or` for existential feasibility problems
129
128
-**Aggregate-only problems:** use a value-only aggregate such as `Sum<_>`, `And`, or a custom `Aggregate` when witnesses are not meaningful
@@ -174,17 +173,19 @@ The CLI now loads, serializes, and brute-force solves problems through the core
174
173
- Add a lowercase alias mapping in `resolve_alias()` (e.g., `"newproblem" => "NewProblem".to_string()`)
175
174
- Only add short aliases to the `ALIASES` array if the abbreviation is **well-established in the literature** (e.g., MIS, MVC, SAT, TSP, CVP are standard; "KS" for Knapsack or "BP" for BinPacking are NOT — do not invent new abbreviations)
176
175
177
-
## Step 4.5: Add CLI creation support
176
+
## Step 4.5: Add construction support
178
177
179
-
CLI creation is **schema-driven** — `pred create <ProblemName>` automatically maps `ProblemSchemaEntry` fields to CLI flags via `snake_case → kebab-case` convention. No match arm in `create.rs` is needed.
178
+
CLI and MCP construction are registry-driven. Do not edit either frontend to recognize a model name.
180
179
181
-
1.**Ensure CLI flags exist** in `problemreductions-cli/src/cli.rs` (`CreateArgs` struct) for each field in your `ProblemSchemaEntry`. The flag name must match the field name via `snake_case → kebab-case` (e.g., field `edge_weights` → flag `--edge-weights`). If a flag already exists with the right name, you're done.
180
+
1.If user-facing inputs exactly match persisted JSON fields, do nothing. The ordinary `declare_variants!` entry uses `ProblemSchemaEntry.fields` as required construction inputs and deserializes the model directly.
182
181
183
-
2.**Add new CLI flags** only if the problem needs flags not already present. Add them to `CreateArgs` and update `all_data_flags_empty()` accordingly. Also add entries to the `flag_map()` method on `CreateArgs`.
182
+
2.If construction has derived fields, renamed inputs, defaults depending on other inputs, or a composite value assembled from multiple inputs, define a model-local DTO with `#[derive(Deserialize, CreateSpec)]`. Its named fields are the complete public construction contract. Use `Option<T>` only for genuinely optional inputs, doc comments for help text, and `#[create(codec = "...")]` when the transport syntax cannot be inferred from the Rust type. Set `ProblemSchemaEntry.fields` to `LocalCreateSpec::FIELDS` so the catalog and executable constructor share the derived metadata.
184
183
185
-
3.**Add type parser support** if the field uses a type not yet handled by `parse_field_value()` in `create.rs`. Check the existing type dispatch table — most standard types (`Vec<i32>`, `Vec<usize>`, `Vec<(usize, usize)>`, graph types, etc.) are already covered. Only add a new parser for genuinely new types.
184
+
3.Implement `TryFrom<LocalCreateSpec> for Model`. Validate before calling constructors that assert or panic, return a descriptive error, compute derived state there, and build the canonical model value.
186
185
187
-
4.**Schema alignment**: The `ProblemSchemaEntry` fields should list **constructor parameters** (what the user provides), not internal derived fields. For example, if `m` and `n` are derived from a matrix, only list `matrix` and `k` in the schema. Field names must match the struct field names exactly (used for JSON serialization and CLI flag mapping).
186
+
4. Register the spec on each applicable variant: `default Model => "..." create LocalCreateSpec`. Both frontends then discover the inputs automatically and serialize the constructed typed model back to canonical persisted JSON.
187
+
188
+
5. A new reusable external syntax may add one transport codec. It must dispatch by codec/type, never by canonical model name. Unknown or missing inputs are rejected by the core construction contract.
188
189
189
190
## Step 4.6: Add canonical model example to example_db
190
191
@@ -314,9 +315,9 @@ Structural and quality review is handled by the `review-pipeline` stage, not her
314
315
| Forgetting CLI alias | Must add lowercase entry in `problem_name.rs``resolve_alias()`|
315
316
| Adding a hand-written decision model | Use `Decision<P>` wrapper instead — see `decision_problem_meta!` + `register_decision_variant!` in `src/models/graph/minimum_vertex_cover.rs` for the pattern |
316
317
| Inventing short aliases | Only use well-established literature abbreviations (MIS, SAT, TSP); do NOT invent new ones |
317
-
|Forgetting CLI flags | Schema-driven create needs matching CLI flags in `CreateArgs` for each `ProblemSchemaEntry` field (snake_case → kebab-case). Also add to `flag_map()`. |
318
-
|Missing type parser | If the problem uses a new field type, add a handler in `parse_field_value()` in `create.rs`|
319
-
|Schema lists derived fields | Schema should list constructor params, not internal fields (e.g., `matrix, k` not `matrix, m, n, k`)|
318
+
|Adding frontend model-name branches | Construction is model-owned. Use a local `CreateSpec` and register it with `declare_variants!`; CLI and MCP must discover it. |
319
+
|Hand-maintaining custom construction fields twice | Derive `CreateSpec`, use `LocalCreateSpec::FIELDS` in `ProblemSchemaEntry`, and register the same type in `declare_variants!`.|
320
+
|Calling a panicking constructor from `TryFrom<CreateSpec>`| Validate the spec first and return a descriptive conversion error.|
320
321
| Missing canonical model example | Add a builder in `src/example_db/model_builders.rs` and keep it aligned with paper/example workflows |
321
322
| Paper example not tested | Must include `test_<name>_paper_example` that verifies the exact instance, solution, and solution count shown in the paper |
322
323
| Claiming direct ILP solving but leaving `<Problem> -> ILP` for later | If the issue promises a direct ILP path, implement that rule in the same PR with exact overhead metadata and production-level ILP tests |
0 commit comments