Skip to content

Commit 22c4b05

Browse files
GiggleLiuclaude
andauthored
refactor: schema-driven pred create (11K → 2.3K lines) (#1008)
* docs: add schema-driven create.rs refactor design spec Design for replacing the 11K-line create.rs with a schema-driven generic dispatch using existing registry factory functions. Targets ~73% line reduction by eliminating the 5,400-line match statement. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * docs: update design spec with Codex review findings - Fix problem count (177 → 189) - Expand type parser table from 16 to 52 types in 3 categories - Add serde edge cases section (try_from, from, skip, custom BigUint) - Add Appendix A with complete flag→field mismatch list - Add generic resolution notes for W, W::Sum, Vec<Vec<W>> Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * Phase 1: align create CLI flags with schema names * Phase 4: add CreateArgs flag map * Phase 2: add schema field parser registry * Phase 3: add schema-driven create builder * Phase 6: wire schema-driven create with fallback * Phase 5: generate create help from schema examples * refactor: expand schema-driven create coverage * refactor: remove legacy create match arms * chore: clean schema-driven create refactor * docs: update skills and CLAUDE.md for schema-driven create - add-model Step 4.5: replace "add match arm" with schema-driven instructions - review-structural check 13: replace grep for problem name with schema field→flag verification - CLAUDE.md Extension Points: document schema-driven create convention Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: dedup all_data_flags_empty, remove legacy flag_map aliases, enforce schema naming - Remove 16 duplicate field checks in all_data_flags_empty() - Remove backward-compat aliases ("sets", "query") from flag_map(); schema-derived names ("subsets", "query-attribute") are canonical - Map schema field "sets" → "subsets" in help_flag_name for consistency - Add CLAUDE.md rule: CLI flag names must match schema field names Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 2c81f94 commit 22c4b05

10 files changed

Lines changed: 7064 additions & 8938 deletions

File tree

.claude/CLAUDE.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,9 +172,11 @@ Reduction graph nodes use variant key-value pairs from `Problem::variant()`:
172172

173173
### Extension Points
174174
- 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
175+
- **CLI creation is schema-driven:** `pred create` automatically maps `ProblemSchemaEntry` fields to CLI flags via `snake_case → kebab-case` convention. New models need only: (1) matching CLI flags in `CreateArgs` + `flag_map()`, and (2) type parser support in `parse_field_value()` if using a new field type. No match arm in `create.rs` is needed.
176+
- **CLI flag names must match schema field names.** The canonical name for a CLI flag is the schema field name in kebab-case (e.g., schema field `universe_size``--universe-size`, field `subsets``--subsets`). Old aliases (e.g., `--universe`, `--sets`) may exist as clap `alias` for backward compatibility at the clap level, but `flag_map()`, help text, error messages, and documentation must use the schema-derived name. Do not add new backward-compat aliases; if a field is renamed in the schema, update the CLI flag name to match.
175177
- Aggregate-only models are first-class in `declare_variants!`; aggregate-only reduction edges still need manual `ReductionEntry` wiring because `#[reduction]` only registers witness/config reductions today
176178
- Exact registry dispatch lives in `src/registry/`; alias resolution and partial/default variant resolution live in `problemreductions-cli/src/problem_name.rs`
177-
- `pred create` UX lives in `problemreductions-cli/src/commands/create.rs`
179+
- `pred create` schema-driven dispatch lives in `problemreductions-cli/src/commands/create.rs` (`create_schema_driven()`)
178180
- Canonical paper and CLI examples live in `src/example_db/model_builders.rs` and `src/example_db/rule_builders.rs`
179181

180182
## Conventions

.claude/skills/add-model/SKILL.md

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -175,18 +175,15 @@ The CLI now loads, serializes, and brute-force solves problems through the core
175175

176176
## Step 4.5: Add CLI creation support
177177

178-
Update `problemreductions-cli/src/commands/create.rs` so `pred create <ProblemName>` works:
178+
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.
179179

180-
1. **Add a match arm** in the `create()` function's main `match canonical.as_str()` block. Parse CLI flags and construct the problem:
181-
- Graph-based problems with vertex weights: add to the `"MaximumIndependentSet" | ... | "MaximalIS"` arm
182-
- Problems with unique fields: add a new arm that parses the required flags and calls the constructor
183-
- See existing arms for patterns (e.g., `"BinPacking"` for simple fields, `"MaximumSetPacking"` for set-based)
180+
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.
184181

185-
2. **Add CLI flags** in `problemreductions-cli/src/cli.rs` (`CreateArgs` struct) if the problem needs flags not already present. Update `all_data_flags_empty()` accordingly.
182+
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`.
186183

187-
3. **Update help text** in `CreateArgs`'s `after_help` — add the new problem to the "Flags by problem type" table in `problemreductions-cli/src/cli.rs` (search for `Flags by problem type`).
184+
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.
188185

189-
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.
186+
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).
190187

191188
## Step 4.6: Add canonical model example to example_db
192189

@@ -315,8 +312,8 @@ Structural and quality review is handled by the `review-pipeline` stage, not her
315312
| Wrong `declare_variants!` syntax | Entries no longer use `opt` / `sat`; one entry per problem may be marked `default` |
316313
| Forgetting CLI alias | Must add lowercase entry in `problem_name.rs` `resolve_alias()` |
317314
| Inventing short aliases | Only use well-established literature abbreviations (MIS, SAT, TSP); do NOT invent new ones |
318-
| Forgetting CLI create | Must add creation handler in `commands/create.rs` and flags in `cli.rs` |
319-
| Missing from CLI help table | Must add entry to "Flags by problem type" table in `cli.rs` `after_help` |
315+
| 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()`. |
316+
| Missing type parser | If the problem uses a new field type, add a handler in `parse_field_value()` in `create.rs` |
320317
| Schema lists derived fields | Schema should list constructor params, not internal fields (e.g., `matrix, k` not `matrix, m, n, k`) |
321318
| Missing canonical model example | Add a builder in `src/example_db/model_builders.rs` and keep it aligned with paper/example workflows |
322319
| Paper example not tested | Must include `test_<name>_paper_example` that verifies the exact instance, solution, and solution count shown in the paper |

.claude/skills/review-structural/SKILL.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ Only run if review type includes "model". Given: problem name `P`, category `C`,
6262
| 10 | Re-exported in `models/mod.rs` | `Grep("{P}", "src/models/mod.rs")` |
6363
| 11 | Variant registration exists | `Grep("declare_variants!|VariantEntry", file)` |
6464
| 12 | CLI `resolve_alias` entry | `Grep("{P}", "problemreductions-cli/src/problem_name.rs")` |
65-
| 13 | CLI `create` support | `Grep('"{P}"', "problemreductions-cli/src/commands/create.rs")` |
65+
| 13 | CLI `create` support | Schema-driven: verify each `ProblemSchemaEntry` field has a matching CLI flag in `CreateArgs` (field `snake_case` → flag `kebab-case`). Check `flag_map()` includes the flag. If the field type is unusual, verify `parse_field_value()` handles it. |
6666
| 14 | Canonical model example registered | `Grep("{P}", "src/example_db/model_builders.rs")` |
6767
| 15 | Paper `display-name` entry | `Grep('"{P}"', "docs/paper/reductions.typ")` |
6868
| 16 | Paper `problem-def` block | `Grep('problem-def.*"{P}"', "docs/paper/reductions.typ")` |

0 commit comments

Comments
 (0)