From 71771ab0752ae1a3b567af104ea1e5820ee1799e Mon Sep 17 00:00:00 2001 From: Sean McGovern Date: Thu, 2 Apr 2026 17:57:42 +0000 Subject: [PATCH 1/3] feat(graph): add pre-rebuild-check Claude Code skill Add a skill that runs `fromager graph check`, interprets results, and recommends constraint fixes grouped by leverage. Closes: #1012 --- .claude/commands/pre-rebuild-check.md | 85 +++++++++++++++++++++++++++ .gitignore | 3 +- 2 files changed, 87 insertions(+), 1 deletion(-) create mode 100644 .claude/commands/pre-rebuild-check.md diff --git a/.claude/commands/pre-rebuild-check.md b/.claude/commands/pre-rebuild-check.md new file mode 100644 index 00000000..9de87639 --- /dev/null +++ b/.claude/commands/pre-rebuild-check.md @@ -0,0 +1,85 @@ +Analyze a fromager build graph and recommend how to eliminate wasted wheel builds before the next bootstrap. + +## Step 1: Run the check + +Parse $ARGUMENTS for a graph.json path and any flags (`--json`, `--constraints`). If no path is found, ask the user. + +```bash +fromager graph check [flags] +``` + +## Step 2: Respond based on the outcome + +### All checks pass + +One line. Offer to compare against another graph if relevant. + +### Structural failures (dangling edges or cycles) + +These block everything — don't analyze conflicts. Report what failed: +- **Dangling edges**: which packages are missing from the graph +- **Cycles**: which packages form the cycle + +Self-loops are warnings (exit 0). Mention briefly, don't treat as blockers. + +### Version conflicts found + +Present build efficiency first, then conflicts grouped by leverage. + +**At scale (5+ conflicts):** Group by binding parent. One parent that binds 4 packages is one line, not four. Show the top binding parents ranked by how many packages they'd free, then summarize the rest. + +**Per conflict**, present problem and fix together: + +> **``** — , bound by `` (``) +> → + +**Collapsible** recommendations: +- Internal binding parent → "relax the specifier in ``" +- Exact `==` pin → "upgrade `` (can't relax an exact pin)" +- Quick workaround → "add `==` to constraints.txt" + +**Required** → blocker. `write_constraints_file` will fail. The binding parent must change before rebuilding. + +## Step 3: Offer artifacts and next steps + +After presenting findings, proactively offer: + +- **Constraints block**: Run `fromager graph check --constraints ` and present the output as a ready-to-paste block for constraints.txt. +- **Binding parent detail**: "Want me to check the specifiers on ``?" when a binding parent drives multiple conflicts. +- **Comparison**: If the user has another graph (previous build, different accelerator), offer to diff: "Want to compare against ``?" + +## What to trust + +- **Collapsible is a guarantee.** The check is conservative relative to `write_constraints_file`. Don't hedge — recommend with confidence. +- **Required is conservative.** The resolver may cascade-resolve some. Say "will likely fail" not "will fail." + +## Don't + +- Don't restate the raw output — interpret it +- Don't explain how the tool works +- Don't list every conflict individually when grouping by parent is clearer +- Don't suggest fixes for required conflicts beyond "update the binding parent" + +## Example response + +For a graph with 419 wheels, 3 collapsible conflicts, and 1 required: + +> **419 wheels built, 3 extra.** 1 required conflict blocks the next build. +> +> **Blocker:** +> - **`tokenizers`** — required, bound by `transformers==4.40.0` (`tokenizers<0.20,>=0.19`). No pin satisfies all consumers. Update transformers before rebuilding. +> +> **Eliminate 3 extra builds:** +> - **`datasets`** and **`huggingface-hub`** — both bound by `unsloth-zoo==0.1.0`. Relaxing unsloth-zoo's specifiers frees both. Pin: `datasets==2.20.0`, `huggingface-hub==0.23.0` +> - **`fsspec`** — bound by `datasets==2.19.0` (`fsspec>=2023.1.0,<2024.6.0`). Pin: `fsspec==2024.5.0` +> +> Ready-to-paste constraints: +> ``` +> datasets==2.20.0 +> huggingface-hub==0.23.0 +> fsspec==2024.5.0 +> ``` +> +> Want me to check unsloth-zoo's specifiers, or compare against a previous build? + +$ARGUMENTS diff --git a/.gitignore b/.gitignore index 874584f2..23ad291c 100644 --- a/.gitignore +++ b/.gitignore @@ -252,5 +252,6 @@ __marimo__/ # Misc .skip-coverage -.claude +.claude/* +!.claude/commands/ /.beads/ From 793408e51fcac38c98f54168626dcda1fd801ad9 Mon Sep 17 00:00:00 2001 From: Sean McGovern Date: Thu, 2 Apr 2026 18:15:58 +0000 Subject: [PATCH 2/3] fix(graph): coderabbit review fix Use "will likely fail" consistently for required conflicts. --- .claude/commands/pre-rebuild-check.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.claude/commands/pre-rebuild-check.md b/.claude/commands/pre-rebuild-check.md index 9de87639..8cd725d7 100644 --- a/.claude/commands/pre-rebuild-check.md +++ b/.claude/commands/pre-rebuild-check.md @@ -38,7 +38,7 @@ Present build efficiency first, then conflicts grouped by leverage. - Exact `==` pin → "upgrade `` (can't relax an exact pin)" - Quick workaround → "add `==` to constraints.txt" -**Required** → blocker. `write_constraints_file` will fail. The binding parent must change before rebuilding. +**Required** → blocker. `write_constraints_file` will likely fail. The binding parent must change before rebuilding. ## Step 3: Offer artifacts and next steps From 7fedf3ce3521d3c6bde1853f19f62a545cee1461 Mon Sep 17 00:00:00 2001 From: Sean McGovern Date: Thu, 2 Apr 2026 18:21:35 +0000 Subject: [PATCH 3/3] fix(graph): fix mdformat lint --- .claude/commands/pre-rebuild-check.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.claude/commands/pre-rebuild-check.md b/.claude/commands/pre-rebuild-check.md index 8cd725d7..e50da9c6 100644 --- a/.claude/commands/pre-rebuild-check.md +++ b/.claude/commands/pre-rebuild-check.md @@ -17,6 +17,7 @@ One line. Offer to compare against another graph if relevant. ### Structural failures (dangling edges or cycles) These block everything — don't analyze conflicts. Report what failed: + - **Dangling edges**: which packages are missing from the graph - **Cycles**: which packages form the cycle @@ -30,10 +31,11 @@ Present build efficiency first, then conflicts grouped by leverage. **Per conflict**, present problem and fix together: -> **``** — , bound by `` (``) +> **``** — \, bound by `` (``) > → **Collapsible** recommendations: + - Internal binding parent → "relax the specifier in ``" - Exact `==` pin → "upgrade `` (can't relax an exact pin)" - Quick workaround → "add `==` to constraints.txt" @@ -67,13 +69,16 @@ For a graph with 419 wheels, 3 collapsible conflicts, and 1 required: > **419 wheels built, 3 extra.** 1 required conflict blocks the next build. > > **Blocker:** +> > - **`tokenizers`** — required, bound by `transformers==4.40.0` (`tokenizers<0.20,>=0.19`). No pin satisfies all consumers. Update transformers before rebuilding. > > **Eliminate 3 extra builds:** +> > - **`datasets`** and **`huggingface-hub`** — both bound by `unsloth-zoo==0.1.0`. Relaxing unsloth-zoo's specifiers frees both. Pin: `datasets==2.20.0`, `huggingface-hub==0.23.0` > - **`fsspec`** — bound by `datasets==2.19.0` (`fsspec>=2023.1.0,<2024.6.0`). Pin: `fsspec==2024.5.0` > > Ready-to-paste constraints: +> > ``` > datasets==2.20.0 > huggingface-hub==0.23.0