From 90aecf2a2dac4377b4f6b7f0b5a71785556f811f Mon Sep 17 00:00:00 2001 From: Fabro Date: Thu, 19 Mar 2026 21:10:30 -0400 Subject: [PATCH] checkpoint MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ⚒️ Generated with [Fabro](https://fabro.sh) --- checkpoint.json | 39 +++++-- nodes/simplify_gpt/prompt.md | 139 ++++++++++++++++++++++++ nodes/simplify_gpt/status.json | 6 ++ nodes/simplify_opus/diff.patch | 188 +++++++++++++++++++++++++++++++++ 4 files changed, 361 insertions(+), 11 deletions(-) create mode 100644 nodes/simplify_gpt/prompt.md create mode 100644 nodes/simplify_gpt/status.json create mode 100644 nodes/simplify_opus/diff.patch diff --git a/checkpoint.json b/checkpoint.json index 4c0c95045..eafdededb 100644 --- a/checkpoint.json +++ b/checkpoint.json @@ -1,13 +1,14 @@ { - "timestamp": "2026-03-20T01:10:27.379698Z", - "current_node": "simplify_opus", + "timestamp": "2026-03-20T01:10:30.890623Z", + "current_node": "simplify_gpt", "completed_nodes": [ "start", "toolchain", "preflight_compile", "preflight_lint", "implement", - "simplify_opus" + "simplify_opus", + "simplify_gpt" ], "node_retries": { "preflight_lint": 1, @@ -15,25 +16,28 @@ "preflight_compile": 1, "start": 1, "toolchain": 1, - "simplify_opus": 1 + "simplify_opus": 1, + "simplify_gpt": 1 }, "context_values": { "internal.retry_count.preflight_compile": 1, "thread.toolchain.current_node": "preflight_compile", "thread.start.current_node": "toolchain", "response.simplify_opus": "Clean. Here's a summary of what was fixed:\n\n## Summary\n\n**Issue found and fixed: Copy-paste duplication between `StylesheetModelKnownRule` and `NodeModelKnownRule`**\n\nThe new `NodeModelKnownRule` had nearly identical model and provider validation logic copied from `StylesheetModelKnownRule`, with only the context string and `node_id` differing.\n\n**Fix:** Extracted two shared helper functions in `rules.rs`:\n- `check_model_known(rule_name, model, context, node_id) -> Option` — validates a model name against the catalog\n- `check_provider_known(rule_name, provider, context, node_id) -> Option` — validates a provider name against `Provider::ALL`\n\nBoth `StylesheetModelKnownRule` and `NodeModelKnownRule` now call these helpers, passing their respective context strings (`\"in stylesheet rule '#foo'\"` vs `\"on node 'bar'\"`). This eliminates ~30 lines of duplicated logic.\n\n**Other findings (no action needed):**\n- **Missing trailing newline in catalog.json**: Already resolved (file has a trailing newline).\n- **Efficiency**: No issues — validation runs on a cold CLI path, all operations are proportional to graph size.\n- **Diagnostic builder pattern**: Pre-existing pattern across all ~20 rules, out of scope for this change.", + "thread.simplify_opus.current_node": "simplify_gpt", "graph.model_stylesheet": "\n * { backend: api; model: claude-opus-4-6;}\n ", "internal.node_visit_count": 1, "internal.retry_count.start": 1, - "failure_class": "", - "outcome": "success", + "internal.retry_count.simplify_gpt": 1, + "failure_class": "deterministic", + "outcome": "fail", "internal.retry_count.preflight_lint": 1, "graph.goal": "# Plan: Add node-level model validation + missing catalog aliases\n\n## Context\n\nRunning `fabro run` with `model=\"gpt-54\"` on a workflow node fails at runtime with `LLM error: Not found on anthropic: model: gpt-54`. Two issues contribute:\n\n1. `fabro validate` doesn't warn about unknown model names on **nodes** (only validates stylesheet models via `StylesheetModelKnownRule`)\n2. The catalog is missing hyphenated aliases like `gpt-54` for `gpt-5.4` (only has `gpt54`)\n\n## Step 1: Add hyphenated aliases to catalog\n\n**File: `lib/crates/fabro-llm/src/catalog.json`**\n\n| Model ID | Current aliases | Add |\n|---|---|---|\n| `gpt-5.4` (line 161) | `[\"gpt54\"]` | `\"gpt-54\"` |\n| `gpt-5.4-pro` (line 178) | `[\"gpt54-pro\"]` | `\"gpt-54-pro\"` |\n| `gpt-5.4-mini` (line 194) | `[\"gpt54-mini\"]` | `\"gpt-54-mini\"` |\n\n**File: `lib/crates/fabro-llm/src/catalog.rs`** — add alias resolution tests:\n- `gpt_54_hyphenated_alias` → asserts `get_model_info(\"gpt-54\")` resolves to `gpt-5.4`\n- `gpt_54_pro_hyphenated_alias` → same for `gpt-54-pro`\n- `gpt_54_mini_hyphenated_alias` → same for `gpt-54-mini`\n\nUpdate insta snapshots (`cargo insta review`) for `gpt_5_4_in_catalog` and `gpt_5_4_pro_in_catalog`.\n\n## Step 2: Add `NodeModelKnownRule`\n\n**File: `lib/crates/fabro-validate/src/rules.rs`**\n\nAdd `NodeModelKnownRule` right after `StylesheetModelKnownRule` (after line 977). Mirrors the stylesheet rule but iterates nodes:\n\n- Iterate `graph.nodes.values()`\n- If `node.model()` is `Some` and `get_model_info()` returns `None` → emit `Severity::Warning`\n- If `node.provider()` is `Some` and `Provider::from_str()` fails → emit `Severity::Warning`\n- Set `node_id: Some(node.id.clone())` on each diagnostic\n\nRegister `Box::new(NodeModelKnownRule)` in `built_in_rules()` (line 33, after `StylesheetModelKnownRule`).\n\n**Tests** (following existing `stylesheet_model_known_rule_*` pattern):\n- `node_model_known_rule_valid_model` — known model, no warnings\n- `node_model_known_rule_unknown_model` — unknown model, 1 warning with model name and node ID\n- `node_model_known_rule_alias` — alias like `\"opus\"`, no warnings\n- `node_model_known_rule_unknown_provider` — bad provider, 1 warning\n- `node_model_known_rule_no_model_no_provider` — plain node, no warnings\n\n## Step 3: Fix the workflow\n\n**File: `fabro/workflows/implement/workflow.fabro` line 19**\n\nChange `model=\"gpt-54\"` to `model=\"gpt-54\"` (now valid after Step 1 adds the alias). No change needed — it will just work.\n\n## Verification\n\n```bash\ncargo test -p fabro-llm\ncargo insta review # accept updated snapshots\ncargo test -p fabro-validate\ncargo clippy --workspace -- -D warnings\ncargo fmt --check --all\n```\n\nThen run `fabro validate fabro/workflows/implement/workflow.fabro` to confirm no warnings.\n", - "internal.thread_id": "implement", + "internal.thread_id": "simplify_opus", "internal.run_id": "01KM4C6R7M1XZF086NV6F0S7JS", "thread.implement.current_node": "simplify_opus", "last_stage": "simplify_opus", - "failure_signature": "", + "failure_signature": "simplify_gpt|deterministic|api_deterministic|anthropic|not_found", "internal.retry_count.simplify_opus": 1, "internal.fidelity": "compact", "internal.retry_count.implement": 1, @@ -45,8 +49,8 @@ "thread.preflight_compile.current_node": "preflight_lint", "graph.rankdir": "LR", "command.output": "", - "current_node": "simplify_opus", - "current.preamble": "Goal: # Plan: Add node-level model validation + missing catalog aliases\n\n## Context\n\nRunning `fabro run` with `model=\"gpt-54\"` on a workflow node fails at runtime with `LLM error: Not found on anthropic: model: gpt-54`. Two issues contribute:\n\n1. `fabro validate` doesn't warn about unknown model names on **nodes** (only validates stylesheet models via `StylesheetModelKnownRule`)\n2. The catalog is missing hyphenated aliases like `gpt-54` for `gpt-5.4` (only has `gpt54`)\n\n## Step 1: Add hyphenated aliases to catalog\n\n**File: `lib/crates/fabro-llm/src/catalog.json`**\n\n| Model ID | Current aliases | Add |\n|---|---|---|\n| `gpt-5.4` (line 161) | `[\"gpt54\"]` | `\"gpt-54\"` |\n| `gpt-5.4-pro` (line 178) | `[\"gpt54-pro\"]` | `\"gpt-54-pro\"` |\n| `gpt-5.4-mini` (line 194) | `[\"gpt54-mini\"]` | `\"gpt-54-mini\"` |\n\n**File: `lib/crates/fabro-llm/src/catalog.rs`** — add alias resolution tests:\n- `gpt_54_hyphenated_alias` → asserts `get_model_info(\"gpt-54\")` resolves to `gpt-5.4`\n- `gpt_54_pro_hyphenated_alias` → same for `gpt-54-pro`\n- `gpt_54_mini_hyphenated_alias` → same for `gpt-54-mini`\n\nUpdate insta snapshots (`cargo insta review`) for `gpt_5_4_in_catalog` and `gpt_5_4_pro_in_catalog`.\n\n## Step 2: Add `NodeModelKnownRule`\n\n**File: `lib/crates/fabro-validate/src/rules.rs`**\n\nAdd `NodeModelKnownRule` right after `StylesheetModelKnownRule` (after line 977). Mirrors the stylesheet rule but iterates nodes:\n\n- Iterate `graph.nodes.values()`\n- If `node.model()` is `Some` and `get_model_info()` returns `None` → emit `Severity::Warning`\n- If `node.provider()` is `Some` and `Provider::from_str()` fails → emit `Severity::Warning`\n- Set `node_id: Some(node.id.clone())` on each diagnostic\n\nRegister `Box::new(NodeModelKnownRule)` in `built_in_rules()` (line 33, after `StylesheetModelKnownRule`).\n\n**Tests** (following existing `stylesheet_model_known_rule_*` pattern):\n- `node_model_known_rule_valid_model` — known model, no warnings\n- `node_model_known_rule_unknown_model` — unknown model, 1 warning with model name and node ID\n- `node_model_known_rule_alias` — alias like `\"opus\"`, no warnings\n- `node_model_known_rule_unknown_provider` — bad provider, 1 warning\n- `node_model_known_rule_no_model_no_provider` — plain node, no warnings\n\n## Step 3: Fix the workflow\n\n**File: `fabro/workflows/implement/workflow.fabro` line 19**\n\nChange `model=\"gpt-54\"` to `model=\"gpt-54\"` (now valid after Step 1 adds the alias). No change needed — it will just work.\n\n## Verification\n\n```bash\ncargo test -p fabro-llm\ncargo insta review # accept updated snapshots\ncargo test -p fabro-validate\ncargo clippy --workspace -- -D warnings\ncargo fmt --check --all\n```\n\nThen run `fabro validate fabro/workflows/implement/workflow.fabro` to confirm no warnings.\n\n\n## Completed stages\n- **toolchain**: success\n - Script: `command -v cargo >/dev/null || { curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y && sudo ln -sf $HOME/.cargo/bin/* /usr/local/bin/; }; cargo --version 2>&1`\n - Stdout:\n ```\n cargo 1.94.0 (85eff7c80 2026-01-15)\n ```\n - Stderr: (empty)\n- **preflight_compile**: success\n - Script: `cargo check -q --workspace 2>&1`\n - Stdout: (empty)\n - Stderr: (empty)\n- **preflight_lint**: success\n - Script: `cargo clippy -q --workspace -- -D warnings 2>&1`\n - Stdout: (empty)\n - Stderr: (empty)\n- **implement**: success\n - Model: claude-opus-4-6, 40.6k tokens in / 7.0k out\n - Files: /home/daytona/workspace/lib/crates/fabro-llm/src/catalog.json, /home/daytona/workspace/lib/crates/fabro-llm/src/catalog.rs, /home/daytona/workspace/lib/crates/fabro-validate/src/rules.rs\n" + "current_node": "simplify_gpt", + "current.preamble": "Goal: # Plan: Add node-level model validation + missing catalog aliases\n\n## Context\n\nRunning `fabro run` with `model=\"gpt-54\"` on a workflow node fails at runtime with `LLM error: Not found on anthropic: model: gpt-54`. Two issues contribute:\n\n1. `fabro validate` doesn't warn about unknown model names on **nodes** (only validates stylesheet models via `StylesheetModelKnownRule`)\n2. The catalog is missing hyphenated aliases like `gpt-54` for `gpt-5.4` (only has `gpt54`)\n\n## Step 1: Add hyphenated aliases to catalog\n\n**File: `lib/crates/fabro-llm/src/catalog.json`**\n\n| Model ID | Current aliases | Add |\n|---|---|---|\n| `gpt-5.4` (line 161) | `[\"gpt54\"]` | `\"gpt-54\"` |\n| `gpt-5.4-pro` (line 178) | `[\"gpt54-pro\"]` | `\"gpt-54-pro\"` |\n| `gpt-5.4-mini` (line 194) | `[\"gpt54-mini\"]` | `\"gpt-54-mini\"` |\n\n**File: `lib/crates/fabro-llm/src/catalog.rs`** — add alias resolution tests:\n- `gpt_54_hyphenated_alias` → asserts `get_model_info(\"gpt-54\")` resolves to `gpt-5.4`\n- `gpt_54_pro_hyphenated_alias` → same for `gpt-54-pro`\n- `gpt_54_mini_hyphenated_alias` → same for `gpt-54-mini`\n\nUpdate insta snapshots (`cargo insta review`) for `gpt_5_4_in_catalog` and `gpt_5_4_pro_in_catalog`.\n\n## Step 2: Add `NodeModelKnownRule`\n\n**File: `lib/crates/fabro-validate/src/rules.rs`**\n\nAdd `NodeModelKnownRule` right after `StylesheetModelKnownRule` (after line 977). Mirrors the stylesheet rule but iterates nodes:\n\n- Iterate `graph.nodes.values()`\n- If `node.model()` is `Some` and `get_model_info()` returns `None` → emit `Severity::Warning`\n- If `node.provider()` is `Some` and `Provider::from_str()` fails → emit `Severity::Warning`\n- Set `node_id: Some(node.id.clone())` on each diagnostic\n\nRegister `Box::new(NodeModelKnownRule)` in `built_in_rules()` (line 33, after `StylesheetModelKnownRule`).\n\n**Tests** (following existing `stylesheet_model_known_rule_*` pattern):\n- `node_model_known_rule_valid_model` — known model, no warnings\n- `node_model_known_rule_unknown_model` — unknown model, 1 warning with model name and node ID\n- `node_model_known_rule_alias` — alias like `\"opus\"`, no warnings\n- `node_model_known_rule_unknown_provider` — bad provider, 1 warning\n- `node_model_known_rule_no_model_no_provider` — plain node, no warnings\n\n## Step 3: Fix the workflow\n\n**File: `fabro/workflows/implement/workflow.fabro` line 19**\n\nChange `model=\"gpt-54\"` to `model=\"gpt-54\"` (now valid after Step 1 adds the alias). No change needed — it will just work.\n\n## Verification\n\n```bash\ncargo test -p fabro-llm\ncargo insta review # accept updated snapshots\ncargo test -p fabro-validate\ncargo clippy --workspace -- -D warnings\ncargo fmt --check --all\n```\n\nThen run `fabro validate fabro/workflows/implement/workflow.fabro` to confirm no warnings.\n\n\n## Completed stages\n- **toolchain**: success\n - Script: `command -v cargo >/dev/null || { curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y && sudo ln -sf $HOME/.cargo/bin/* /usr/local/bin/; }; cargo --version 2>&1`\n - Stdout:\n ```\n cargo 1.94.0 (85eff7c80 2026-01-15)\n ```\n - Stderr: (empty)\n- **preflight_compile**: success\n - Script: `cargo check -q --workspace 2>&1`\n - Stdout: (empty)\n - Stderr: (empty)\n- **preflight_lint**: success\n - Script: `cargo clippy -q --workspace -- -D warnings 2>&1`\n - Stdout: (empty)\n - Stderr: (empty)\n- **implement**: success\n - Model: claude-opus-4-6, 40.6k tokens in / 7.0k out\n - Files: /home/daytona/workspace/lib/crates/fabro-llm/src/catalog.json, /home/daytona/workspace/lib/crates/fabro-llm/src/catalog.rs, /home/daytona/workspace/lib/crates/fabro-validate/src/rules.rs\n- **simplify_opus**: success\n - Model: claude-opus-4-6, 24.7k tokens in / 10.1k out\n - Files: /home/daytona/workspace/lib/crates/fabro-validate/src/rules.rs\n" }, "logs": [], "node_outcomes": { @@ -118,6 +122,15 @@ "status": "success", "duration_ms": 0 }, + "simplify_gpt": { + "status": "fail", + "failure": { + "message": "LLM error: Not found on anthropic: model: gpt-54", + "failure_class": "deterministic", + "failure_signature": "api_deterministic|anthropic|not_found" + }, + "duration_ms": 509 + }, "toolchain": { "status": "success", "context_updates": { @@ -128,11 +141,15 @@ "duration_ms": 39 } }, - "next_node_id": "simplify_gpt", + "next_node_id": "verify", + "loop_failure_signatures": { + "simplify_gpt|deterministic|api_deterministic|anthropic|not_found": 1 + }, "node_visits": { "preflight_compile": 1, "simplify_opus": 1, "toolchain": 1, + "simplify_gpt": 1, "preflight_lint": 1, "start": 1, "implement": 1 diff --git a/nodes/simplify_gpt/prompt.md b/nodes/simplify_gpt/prompt.md new file mode 100644 index 000000000..6839c9c33 --- /dev/null +++ b/nodes/simplify_gpt/prompt.md @@ -0,0 +1,139 @@ +Goal: # Plan: Add node-level model validation + missing catalog aliases + +## Context + +Running `fabro run` with `model="gpt-54"` on a workflow node fails at runtime with `LLM error: Not found on anthropic: model: gpt-54`. Two issues contribute: + +1. `fabro validate` doesn't warn about unknown model names on **nodes** (only validates stylesheet models via `StylesheetModelKnownRule`) +2. The catalog is missing hyphenated aliases like `gpt-54` for `gpt-5.4` (only has `gpt54`) + +## Step 1: Add hyphenated aliases to catalog + +**File: `lib/crates/fabro-llm/src/catalog.json`** + +| Model ID | Current aliases | Add | +|---|---|---| +| `gpt-5.4` (line 161) | `["gpt54"]` | `"gpt-54"` | +| `gpt-5.4-pro` (line 178) | `["gpt54-pro"]` | `"gpt-54-pro"` | +| `gpt-5.4-mini` (line 194) | `["gpt54-mini"]` | `"gpt-54-mini"` | + +**File: `lib/crates/fabro-llm/src/catalog.rs`** — add alias resolution tests: +- `gpt_54_hyphenated_alias` → asserts `get_model_info("gpt-54")` resolves to `gpt-5.4` +- `gpt_54_pro_hyphenated_alias` → same for `gpt-54-pro` +- `gpt_54_mini_hyphenated_alias` → same for `gpt-54-mini` + +Update insta snapshots (`cargo insta review`) for `gpt_5_4_in_catalog` and `gpt_5_4_pro_in_catalog`. + +## Step 2: Add `NodeModelKnownRule` + +**File: `lib/crates/fabro-validate/src/rules.rs`** + +Add `NodeModelKnownRule` right after `StylesheetModelKnownRule` (after line 977). Mirrors the stylesheet rule but iterates nodes: + +- Iterate `graph.nodes.values()` +- If `node.model()` is `Some` and `get_model_info()` returns `None` → emit `Severity::Warning` +- If `node.provider()` is `Some` and `Provider::from_str()` fails → emit `Severity::Warning` +- Set `node_id: Some(node.id.clone())` on each diagnostic + +Register `Box::new(NodeModelKnownRule)` in `built_in_rules()` (line 33, after `StylesheetModelKnownRule`). + +**Tests** (following existing `stylesheet_model_known_rule_*` pattern): +- `node_model_known_rule_valid_model` — known model, no warnings +- `node_model_known_rule_unknown_model` — unknown model, 1 warning with model name and node ID +- `node_model_known_rule_alias` — alias like `"opus"`, no warnings +- `node_model_known_rule_unknown_provider` — bad provider, 1 warning +- `node_model_known_rule_no_model_no_provider` — plain node, no warnings + +## Step 3: Fix the workflow + +**File: `fabro/workflows/implement/workflow.fabro` line 19** + +Change `model="gpt-54"` to `model="gpt-54"` (now valid after Step 1 adds the alias). No change needed — it will just work. + +## Verification + +```bash +cargo test -p fabro-llm +cargo insta review # accept updated snapshots +cargo test -p fabro-validate +cargo clippy --workspace -- -D warnings +cargo fmt --check --all +``` + +Then run `fabro validate fabro/workflows/implement/workflow.fabro` to confirm no warnings. + + +## Completed stages +- **toolchain**: success + - Script: `command -v cargo >/dev/null || { curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y && sudo ln -sf $HOME/.cargo/bin/* /usr/local/bin/; }; cargo --version 2>&1` + - Stdout: + ``` + cargo 1.94.0 (85eff7c80 2026-01-15) + ``` + - Stderr: (empty) +- **preflight_compile**: success + - Script: `cargo check -q --workspace 2>&1` + - Stdout: (empty) + - Stderr: (empty) +- **preflight_lint**: success + - Script: `cargo clippy -q --workspace -- -D warnings 2>&1` + - Stdout: (empty) + - Stderr: (empty) +- **implement**: success + - Model: claude-opus-4-6, 40.6k tokens in / 7.0k out + - Files: /home/daytona/workspace/lib/crates/fabro-llm/src/catalog.json, /home/daytona/workspace/lib/crates/fabro-llm/src/catalog.rs, /home/daytona/workspace/lib/crates/fabro-validate/src/rules.rs +- **simplify_opus**: success + - Model: claude-opus-4-6, 24.7k tokens in / 10.1k out + - Files: /home/daytona/workspace/lib/crates/fabro-validate/src/rules.rs + + +# Simplify: Code Review and Cleanup + +Review all changed files for reuse, quality, and efficiency. Fix any issues found. + +## Phase 1: Identify Changes + +Run git diff (or git diff HEAD if there are staged changes) to see what changed. If there are no git changes, review the most recently modified files that the user mentioned or that you edited earlier in this conversation. + +## Phase 2: Launch Three Review Agents in Parallel + +Use the Agent tool to launch all three agents concurrently in a single message. Pass each agent the full diff so it has the complete context. + +### Agent 1: Code Reuse Review + +For each change: + +1. Search for existing utilities and helpers that could replace newly written code. Use Grep to find similar patterns elsewhere in the codebase — common locations are utility directories, shared modules, and files adjacent to the changed ones. +2. Flag any new function that duplicates existing functionality. Suggest the existing function to use instead. +3. Flag any inline logic that could use an existing utility — hand-rolled string manipulation, manual path handling, custom environment checks, ad-hoc type guards, and similar patterns are common candidates. + +Note: This is a greenfield app, so focus on maximizing simplicity and don't worry about changing things to achieve it. + +### Agent 2: Code Quality Review + +Review the same changes for hacky patterns: + +1. Redundant state: state that duplicates existing state, cached values that could be derived, observers/effects that could be direct calls +2. Parameter sprawl: adding new parameters to a function instead of generalizing or restructuring existing ones +3. Copy-paste with slight variation: near-duplicate code blocks that should be unified with a shared abstraction +4. Leaky abstractions: exposing internal details that should be encapsulated, or breaking existing abstraction boundaries +5. Stringly-typed code: using raw strings where constants, enums (string unions), or branded types already exist in the codebase + +Note: This is a greenfield app, so be aggressive in optimizing quality. + +### Agent 3: Efficiency Review + +Review the same changes for efficiency: + +1. Unnecessary work: redundant computations, repeated file reads, duplicate network/API calls, N+1 patterns +2. Missed concurrency: independent operations run sequentially when they could run in parallel +3. Hot-path bloat: new blocking work added to startup or per-request/per-render hot paths +4. Unnecessary existence checks: pre-checking file/resource existence before operating (TOCTOU anti-pattern) — operate directly and handle the error +5. Memory: unbounded data structures, missing cleanup, event listener leaks +6. Overly broad operations: reading entire files when only a portion is needed, loading all items when filtering for one + +## Phase 3: Fix Issues + +Wait for all three agents to complete. Aggregate their findings and fix each issue directly. If a finding is a false positive or not worth addressing, note it and move on — do not argue with the finding, just skip it. + +When done, briefly summarize what was fixed (or confirm the code was already clean). \ No newline at end of file diff --git a/nodes/simplify_gpt/status.json b/nodes/simplify_gpt/status.json new file mode 100644 index 000000000..296cc4574 --- /dev/null +++ b/nodes/simplify_gpt/status.json @@ -0,0 +1,6 @@ +{ + "status": "fail", + "notes": null, + "failure_reason": "LLM error: Not found on anthropic: model: gpt-54", + "timestamp": "2026-03-20T01:10:30.890089+00:00" +} \ No newline at end of file diff --git a/nodes/simplify_opus/diff.patch b/nodes/simplify_opus/diff.patch new file mode 100644 index 000000000..b9f8e273a --- /dev/null +++ b/nodes/simplify_opus/diff.patch @@ -0,0 +1,188 @@ +diff --git a/lib/crates/fabro-llm/src/.catalog.rs.pending-snap b/lib/crates/fabro-llm/src/.catalog.rs.pending-snap +deleted file mode 100644 +index 811b6086..00000000 +--- a/lib/crates/fabro-llm/src/.catalog.rs.pending-snap ++++ /dev/null +@@ -1,16 +0,0 @@ +-{"run_id":"1773968658-14885991","line":492,"new":{"module_name":"fabro_llm__catalog__tests","snapshot_name":"gpt_5_4_in_catalog","metadata":{"source":"lib/crates/fabro-llm/src/catalog.rs","assertion_line":492,"expression":"m"},"snapshot":"ModelInfo {\n id: \"gpt-5.4\",\n provider: \"openai\",\n family: \"gpt-5\",\n display_name: \"GPT-5.4\",\n limits: ModelLimits {\n context_window: 1047576,\n max_output: Some(\n 128000,\n ),\n },\n training: Some(\n \"2025-08-31\",\n ),\n features: ModelFeatures {\n tools: true,\n vision: true,\n reasoning: true,\n },\n costs: ModelCosts {\n input_cost_per_mtok: Some(\n 2.5,\n ),\n output_cost_per_mtok: Some(\n 15.0,\n ),\n cache_input_cost_per_mtok: Some(\n 0.25,\n ),\n },\n estimated_output_tps: Some(\n 70.0,\n ),\n aliases: [\n \"gpt54\",\n \"gpt-54\",\n ],\n default: true,\n}"},"old":{"module_name":"fabro_llm__catalog__tests","metadata":{},"snapshot":"ModelInfo {\n id: \"gpt-5.4\",\n provider: \"openai\",\n family: \"gpt-5\",\n display_name: \"GPT-5.4\",\n limits: ModelLimits {\n context_window: 1047576,\n max_output: Some(\n 128000,\n ),\n },\n training: Some(\n \"2025-08-31\",\n ),\n features: ModelFeatures {\n tools: true,\n vision: true,\n reasoning: true,\n },\n costs: ModelCosts {\n input_cost_per_mtok: Some(\n 2.5,\n ),\n output_cost_per_mtok: Some(\n 15.0,\n ),\n cache_input_cost_per_mtok: Some(\n 0.25,\n ),\n },\n estimated_output_tps: Some(\n 70.0,\n ),\n aliases: [\n \"gpt54\",\n ],\n default: true,\n}"}} +-{"run_id":"1773968658-14885991","line":537,"new":{"module_name":"fabro_llm__catalog__tests","snapshot_name":"gpt_5_4_pro_in_catalog","metadata":{"source":"lib/crates/fabro-llm/src/catalog.rs","assertion_line":537,"expression":"m"},"snapshot":"ModelInfo {\n id: \"gpt-5.4-pro\",\n provider: \"openai\",\n family: \"gpt-5\",\n display_name: \"GPT-5.4 Pro\",\n limits: ModelLimits {\n context_window: 1047576,\n max_output: Some(\n 128000,\n ),\n },\n training: Some(\n \"2025-08-31\",\n ),\n features: ModelFeatures {\n tools: true,\n vision: true,\n reasoning: true,\n },\n costs: ModelCosts {\n input_cost_per_mtok: Some(\n 30.0,\n ),\n output_cost_per_mtok: Some(\n 180.0,\n ),\n cache_input_cost_per_mtok: Some(\n 3.0,\n ),\n },\n estimated_output_tps: Some(\n 20.0,\n ),\n aliases: [\n \"gpt54-pro\",\n \"gpt-54-pro\",\n ],\n default: false,\n}"},"old":{"module_name":"fabro_llm__catalog__tests","metadata":{},"snapshot":"ModelInfo {\n id: \"gpt-5.4-pro\",\n provider: \"openai\",\n family: \"gpt-5\",\n display_name: \"GPT-5.4 Pro\",\n limits: ModelLimits {\n context_window: 1047576,\n max_output: Some(\n 128000,\n ),\n },\n training: Some(\n \"2025-08-31\",\n ),\n features: ModelFeatures {\n tools: true,\n vision: true,\n reasoning: true,\n },\n costs: ModelCosts {\n input_cost_per_mtok: Some(\n 30.0,\n ),\n output_cost_per_mtok: Some(\n 180.0,\n ),\n cache_input_cost_per_mtok: Some(\n 3.0,\n ),\n },\n estimated_output_tps: Some(\n 20.0,\n ),\n aliases: [\n \"gpt54-pro\",\n ],\n default: false,\n}"}} +-{"run_id":"1773968695-171443032","line":604,"new":null,"old":null} +-{"run_id":"1773968695-171443032","line":254,"new":null,"old":null} +-{"run_id":"1773968695-171443032","line":333,"new":null,"old":null} +-{"run_id":"1773968695-171443032","line":492,"new":null,"old":null} +-{"run_id":"1773968695-171443032","line":538,"new":null,"old":null} +-{"run_id":"1773968695-171443032","line":386,"new":null,"old":null} +-{"run_id":"1773968695-171443032","line":446,"new":null,"old":null} +-{"run_id":"1773968758-970882052","line":254,"new":null,"old":null} +-{"run_id":"1773968758-970882052","line":604,"new":null,"old":null} +-{"run_id":"1773968758-970882052","line":492,"new":null,"old":null} +-{"run_id":"1773968758-970882052","line":333,"new":null,"old":null} +-{"run_id":"1773968758-970882052","line":386,"new":null,"old":null} +-{"run_id":"1773968758-970882052","line":446,"new":null,"old":null} +-{"run_id":"1773968758-970882052","line":538,"new":null,"old":null} +diff --git a/lib/crates/fabro-llm/src/catalog.json b/lib/crates/fabro-llm/src/catalog.json +index a042b98c..f05f1301 100644 +--- a/lib/crates/fabro-llm/src/catalog.json ++++ b/lib/crates/fabro-llm/src/catalog.json +@@ -326,4 +326,4 @@ + "aliases": ["mercury"], + "default": true + } +-] +\ No newline at end of file ++] +diff --git a/lib/crates/fabro-validate/src/rules.rs b/lib/crates/fabro-validate/src/rules.rs +index 28e1fa71..c9296a6e 100644 +--- a/lib/crates/fabro-validate/src/rules.rs ++++ b/lib/crates/fabro-validate/src/rules.rs +@@ -899,6 +899,53 @@ impl LintRule for ScriptAbsoluteCdRule { + } + } + ++// --- Shared helpers for model/provider validation --- ++ ++fn check_model_known( ++ rule_name: &str, ++ model: &str, ++ context: &str, ++ node_id: Option, ++) -> Option { ++ if fabro_llm::catalog::get_model_info(model).is_some() { ++ return None; ++ } ++ Some(Diagnostic { ++ rule: rule_name.to_string(), ++ severity: Severity::Warning, ++ message: format!( ++ "Unknown model '{model}' {context}. Run `fabro model list` to see available models" ++ ), ++ node_id, ++ edge: None, ++ fix: Some("Use a model ID from `fabro model list`".to_string()), ++ }) ++} ++ ++fn check_provider_known( ++ rule_name: &str, ++ provider: &str, ++ context: &str, ++ node_id: Option, ++) -> Option { ++ if fabro_llm::Provider::from_str(provider).is_ok() { ++ return None; ++ } ++ let valid: Vec<&str> = fabro_llm::Provider::ALL ++ .iter() ++ .map(|p| p.as_str()) ++ .collect(); ++ let valid_str = valid.join(", "); ++ Some(Diagnostic { ++ rule: rule_name.to_string(), ++ severity: Severity::Warning, ++ message: format!("Unknown provider '{provider}' {context}. Valid providers: {valid_str}"), ++ node_id, ++ edge: None, ++ fix: Some(format!("Use one of: {valid_str}")), ++ }) ++} ++ + // --- Rule 20: stylesheet_model_known (WARNING) --- + + struct StylesheetModelKnownRule; +@@ -933,40 +980,19 @@ impl LintRule for StylesheetModelKnownRule { + for rule in &stylesheet.rules { + let label = Self::selector_label(&rule.selector); + for decl in &rule.declarations { ++ let context = format!("in stylesheet rule '{label}'"); + match decl.property.as_str() { + "model" => { +- if fabro_llm::catalog::get_model_info(&decl.value).is_none() { +- diagnostics.push(Diagnostic { +- rule: self.name().to_string(), +- severity: Severity::Warning, +- message: format!( +- "Unknown model '{}' in stylesheet rule '{label}'. Run `fabro model list` to see available models", +- decl.value +- ), +- node_id: None, +- edge: None, +- fix: Some("Use a model ID from `fabro model list`".to_string()), +- }); ++ if let Some(d) = check_model_known(self.name(), &decl.value, &context, None) ++ { ++ diagnostics.push(d); + } + } + "provider" => { +- if fabro_llm::Provider::from_str(&decl.value).is_err() { +- let valid: Vec<&str> = fabro_llm::Provider::ALL +- .iter() +- .map(|p| p.as_str()) +- .collect(); +- diagnostics.push(Diagnostic { +- rule: self.name().to_string(), +- severity: Severity::Warning, +- message: format!( +- "Unknown provider '{}' in stylesheet rule '{label}'. Valid providers: {}", +- decl.value, +- valid.join(", ") +- ), +- node_id: None, +- edge: None, +- fix: Some(format!("Use one of: {}", valid.join(", "))), +- }); ++ if let Some(d) = ++ check_provider_known(self.name(), &decl.value, &context, None) ++ { ++ diagnostics.push(d); + } + } + _ => {} +@@ -989,39 +1015,18 @@ impl LintRule for NodeModelKnownRule { + fn apply(&self, graph: &Graph) -> Vec { + let mut diagnostics = Vec::new(); + for node in graph.nodes.values() { ++ let context = format!("on node '{}'", node.id); ++ let node_id = Some(node.id.clone()); + if let Some(model) = node.model() { +- if fabro_llm::catalog::get_model_info(model).is_none() { +- diagnostics.push(Diagnostic { +- rule: self.name().to_string(), +- severity: Severity::Warning, +- message: format!( +- "Unknown model '{model}' on node '{}'. Run `fabro model list` to see available models", +- node.id +- ), +- node_id: Some(node.id.clone()), +- edge: None, +- fix: Some("Use a model ID from `fabro model list`".to_string()), +- }); ++ if let Some(d) = check_model_known(self.name(), model, &context, node_id.clone()) { ++ diagnostics.push(d); + } + } + if let Some(provider) = node.provider() { +- if fabro_llm::Provider::from_str(provider).is_err() { +- let valid: Vec<&str> = fabro_llm::Provider::ALL +- .iter() +- .map(|p| p.as_str()) +- .collect(); +- diagnostics.push(Diagnostic { +- rule: self.name().to_string(), +- severity: Severity::Warning, +- message: format!( +- "Unknown provider '{provider}' on node '{}'. Valid providers: {}", +- node.id, +- valid.join(", ") +- ), +- node_id: Some(node.id.clone()), +- edge: None, +- fix: Some(format!("Use one of: {}", valid.join(", "))), +- }); ++ if let Some(d) = ++ check_provider_known(self.name(), provider, &context, node_id.clone()) ++ { ++ diagnostics.push(d); + } + } + }