chore(lint): fix all clippy warnings including --tests

Resolve every clippy warning across the workspace when running with
--tests enabled. Previously only library code was lint-clean; test
code had accumulated issues that were invisible without --tests.

Fixes:
- redundant_closure_for_method_calls: |s| s.as_source() -> InterpString::as_source
  (effective_settings, resolve_cli/root/server/features, run_event/record_serde,
  materialize_run) — add InterpString imports where needed
- absolute_paths: inline fabro_types::settings::* paths -> use imports;
  add #![allow(clippy::absolute_paths)] to fabro-cli and fabro-server
  IT test harnesses (matching the existing pattern in integration.rs)
- bool_assert_comparison: assert_eq!(x, true) -> assert!(x)
- needless_raw_string_hashes: r#"..."# -> r"..." where no inner quotes
- field_reassign_with_default: mut + field assign -> struct literal with ..Default
- match_same_arms: merge Timeout | Disconnected arms in attach.rs
- needless_pass_by_value: signal_rx by ref in attach.rs
- unreadable_literal: 9999999999 -> 9_999_999_999
- default_trait_access: Default::default() -> BTreeMap::default()
- items_after_statements: move use to function top
- large_futures: allow in integration.rs test module (test-only, not prod)
- filter_map_bool_then: .filter_map(bool::then) -> .filter().map()

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Bryan Helmkamp 2026-04-10 10:16:24 -04:00
parent 42f8ec271b
commit 76089bd8aa
No known key found for this signature in database
30 changed files with 140 additions and 104 deletions

View file

@ -1080,15 +1080,21 @@ mod tests {
};
let certs_dir = fabro_util::Home::from_env().certs_dir();
assert_eq!(
tls.cert.as_ref().map(|c| c.as_source()),
tls.cert
.as_ref()
.map(fabro_types::settings::InterpString::as_source),
Some(certs_dir.join("server.crt").to_string_lossy().into_owned())
);
assert_eq!(
tls.key.as_ref().map(|c| c.as_source()),
tls.key
.as_ref()
.map(fabro_types::settings::InterpString::as_source),
Some(certs_dir.join("server.key").to_string_lossy().into_owned())
);
assert_eq!(
tls.ca.as_ref().map(|c| c.as_source()),
tls.ca
.as_ref()
.map(fabro_types::settings::InterpString::as_source),
Some(certs_dir.join("ca.crt").to_string_lossy().into_owned())
);
}

View file

@ -488,6 +488,7 @@ fn install_signal_handlers(
}
#[cfg(test)]
#[allow(clippy::absolute_paths)]
mod tests {
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};

View file

@ -83,7 +83,7 @@ fn wait_for_output_signal(
child: &mut std::process::Child,
stdout: &mut impl Read,
stderr_reader: std::thread::JoinHandle<Vec<u8>>,
signal_rx: mpsc::Receiver<()>,
signal_rx: &mpsc::Receiver<()>,
needle: &str,
) -> std::thread::JoinHandle<Vec<u8>> {
let deadline = Instant::now() + SHARED_DAEMON_TIMEOUT;
@ -96,8 +96,7 @@ fn wait_for_output_signal(
.take()
.expect("stderr reader should still be available");
}
Err(mpsc::RecvTimeoutError::Timeout) => {}
Err(mpsc::RecvTimeoutError::Disconnected) => {}
Err(mpsc::RecvTimeoutError::Timeout | mpsc::RecvTimeoutError::Disconnected) => {}
}
if let Some(status) = child.try_wait().expect("attach should stay alive") {
@ -252,8 +251,13 @@ fn attach_before_completion_streams_to_finished_state() {
stderr_bytes
});
let stderr_reader =
wait_for_output_signal(&mut child, &mut stdout, stderr_reader, signal_rx, "✓ start");
let stderr_reader = wait_for_output_signal(
&mut child,
&mut stdout,
stderr_reader,
&signal_rx,
"✓ start",
);
gate.release();
let status = child.wait().expect("attach should exit");
let mut stdout_bytes = Vec::new();

View file

@ -63,7 +63,7 @@ fn run_model_name(settings: &SettingsLayer) -> Option<String> {
.model
.name
.as_ref()
.map(|value| value.as_source())
.map(fabro_types::settings::InterpString::as_source)
}
fn run_model_provider(settings: &SettingsLayer) -> Option<String> {
@ -71,7 +71,7 @@ fn run_model_provider(settings: &SettingsLayer) -> Option<String> {
.model
.provider
.as_ref()
.map(|value| value.as_source())
.map(fabro_types::settings::InterpString::as_source)
}
fn run_inputs(settings: &SettingsLayer) -> &std::collections::HashMap<String, toml::Value> {
@ -102,8 +102,7 @@ fn run_hooks(settings: &SettingsLayer) -> &[fabro_types::settings::run::HookEntr
settings
.run
.as_ref()
.map(|run| run.hooks.as_slice())
.unwrap_or(&[])
.map_or(&[], |run| run.hooks.as_slice())
}
fn run_agent_mcps(
@ -410,6 +409,7 @@ fn settings_local_merges_cli_and_project_defaults() {
#[test]
fn settings_local_workflow_name_applies_run_overlay_and_deep_merges() {
use fabro_types::settings::run::McpEntryLayer;
let context = test_context!();
let project = setup_settings_fixture(&context);
@ -423,8 +423,6 @@ fn settings_local_workflow_name_applies_run_overlay_and_deep_merges() {
.stdout
.clone();
use fabro_types::settings::run::McpEntryLayer;
let cfg = parse_settings(&output);
assert_eq!(run_goal_inline(&cfg).as_deref(), Some("demo goal"));
assert_eq!(run_model_name(&cfg).as_deref(), Some("run-model"));
@ -456,7 +454,7 @@ fn settings_local_workflow_name_applies_run_overlay_and_deep_merges() {
shared_hook
.script
.as_ref()
.map(|s| s.as_source())
.map(fabro_types::settings::InterpString::as_source)
.as_deref(),
Some("echo run")
);
@ -470,7 +468,10 @@ fn settings_local_workflow_name_applies_run_overlay_and_deep_merges() {
match mcps.get("shared").expect("shared mcp") {
McpEntryLayer::Stdio { command, .. } => {
let command = command.as_ref().expect("command");
let parts: Vec<String> = command.iter().map(|c| c.as_source()).collect();
let parts: Vec<String> = command
.iter()
.map(fabro_types::settings::InterpString::as_source)
.collect();
assert_eq!(parts, vec!["echo".to_string(), "run".to_string()]);
}
other => panic!("unexpected MCP transport: {other:?}"),
@ -486,15 +487,21 @@ fn settings_local_workflow_name_applies_run_overlay_and_deep_merges() {
// run.sandbox.env stays sticky merge-by-key per R71.
let env = &sandbox.env;
assert_eq!(
env.get("CLI_ONLY").map(|v| v.as_source()).as_deref(),
env.get("CLI_ONLY")
.map(fabro_types::settings::InterpString::as_source)
.as_deref(),
Some("1")
);
assert_eq!(
env.get("RUN_ONLY").map(|v| v.as_source()).as_deref(),
env.get("RUN_ONLY")
.map(fabro_types::settings::InterpString::as_source)
.as_deref(),
Some("1")
);
assert_eq!(
env.get("SHARED").map(|v| v.as_source()).as_deref(),
env.get("SHARED")
.map(fabro_types::settings::InterpString::as_source)
.as_deref(),
Some("run")
);
}

View file

@ -373,8 +373,8 @@ fn create_persists_requested_overrides_into_store() {
"no_retro": !resolved_run.execution.retros,
"verbose": cli_settings.output.verbosity == fabro_types::settings::cli::OutputVerbosity::Verbose,
"llm": {
"model": resolved_run.model.name.as_ref().map(|value| value.as_source()),
"provider": resolved_run.model.provider.as_ref().map(|value| value.as_source()),
"model": resolved_run.model.name.as_ref().map(fabro_types::settings::InterpString::as_source),
"provider": resolved_run.model.provider.as_ref().map(fabro_types::settings::InterpString::as_source),
},
"sandbox": {
"provider": resolved_run.sandbox.provider,

View file

@ -1,3 +1,5 @@
#![allow(clippy::absolute_paths)]
mod cmd;
mod scenario;
mod support;

View file

@ -183,6 +183,7 @@ mod tests {
use crate::parse::parse_settings_layer;
use fabro_types::settings::InterpString;
use fabro_types::settings::SettingsLayer;
use fabro_types::settings::run::RunGoalLayer;
use fabro_types::settings::server::{ServerLayer, ServerSchedulerLayer, ServerStorageLayer};
use super::{EffectiveSettingsLayers, EffectiveSettingsMode, resolve_settings};
@ -236,7 +237,7 @@ shared = "user"
.as_ref()
.and_then(|run| run.model.as_ref())
.and_then(|model| model.name.as_ref())
.map(|value| value.as_source())
.map(InterpString::as_source)
.as_deref(),
Some("project-model")
);
@ -299,7 +300,7 @@ provider = "openai"
assert_eq!(
match settings.run.as_ref().and_then(|run| run.goal.as_ref()) {
Some(fabro_types::settings::run::RunGoalLayer::Inline(value)) => {
Some(RunGoalLayer::Inline(value)) => {
Some(value.as_source())
}
_ => None,
@ -313,7 +314,7 @@ provider = "openai"
.as_ref()
.and_then(|run| run.model.as_ref())
.and_then(|model| model.name.as_ref())
.map(|value| value.as_source())
.map(InterpString::as_source)
.as_deref(),
Some("workflow-model")
);
@ -323,7 +324,7 @@ provider = "openai"
.as_ref()
.and_then(|run| run.model.as_ref())
.and_then(|model| model.provider.as_ref())
.map(|value| value.as_source())
.map(InterpString::as_source)
.as_deref(),
Some("openai")
);
@ -331,16 +332,18 @@ provider = "openai"
#[test]
fn cli_and_server_domains_from_fabro_toml_are_inert_under_remote_mode() {
let mut server_settings = fabro_types::settings::SettingsLayer::default();
server_settings.server = Some(ServerLayer {
storage: Some(ServerStorageLayer {
root: Some(InterpString::parse("/srv/fabro")),
let server_settings = SettingsLayer {
server: Some(ServerLayer {
storage: Some(ServerStorageLayer {
root: Some(InterpString::parse("/srv/fabro")),
}),
scheduler: Some(ServerSchedulerLayer {
max_concurrent_runs: Some(9),
}),
..ServerLayer::default()
}),
scheduler: Some(ServerSchedulerLayer {
max_concurrent_runs: Some(9),
}),
..ServerLayer::default()
});
..SettingsLayer::default()
};
let project_with_server = layer(
r#"
@ -372,13 +375,13 @@ root = "/tmp/should-be-inert"
.as_ref()
.and_then(|server| server.storage.as_ref())
.and_then(|storage| storage.root.as_ref())
.map(|value| value.as_source())
.map(InterpString::as_source)
.as_deref(),
Some("/srv/fabro")
);
assert_eq!(
match settings.run.as_ref().and_then(|run| run.goal.as_ref()) {
Some(fabro_types::settings::run::RunGoalLayer::Inline(value)) => {
Some(RunGoalLayer::Inline(value)) => {
Some(value.as_source())
}
_ => None,
@ -390,16 +393,18 @@ root = "/tmp/should-be-inert"
#[test]
fn local_daemon_mode_only_applies_server_owned_overrides() {
let mut server_settings = fabro_types::settings::SettingsLayer::default();
server_settings.server = Some(ServerLayer {
storage: Some(ServerStorageLayer {
root: Some(InterpString::parse("/srv/fabro")),
let server_settings = SettingsLayer {
server: Some(ServerLayer {
storage: Some(ServerStorageLayer {
root: Some(InterpString::parse("/srv/fabro")),
}),
scheduler: Some(ServerSchedulerLayer {
max_concurrent_runs: Some(7),
}),
..ServerLayer::default()
}),
scheduler: Some(ServerSchedulerLayer {
max_concurrent_runs: Some(7),
}),
..ServerLayer::default()
});
..SettingsLayer::default()
};
let settings = resolve_settings(
EffectiveSettingsLayers::default(),
@ -414,7 +419,7 @@ root = "/tmp/should-be-inert"
.as_ref()
.and_then(|server| server.storage.as_ref())
.and_then(|storage| storage.root.as_ref())
.map(|value| value.as_source())
.map(InterpString::as_source)
.as_deref(),
Some("/srv/fabro")
);

View file

@ -1,8 +1,8 @@
use fabro_config::parse_settings_layer;
use fabro_config::resolve_cli_from_file;
use fabro_types::settings::SettingsLayer;
use fabro_types::settings::cli::{CliTargetSettings, OutputFormat, OutputVerbosity};
use fabro_types::settings::run::AgentPermissions;
use fabro_types::settings::{InterpString, SettingsLayer};
#[test]
fn resolves_cli_defaults_from_empty_settings() {
@ -77,11 +77,11 @@ level = "debug"
.model
.provider
.as_ref()
.map(|value| value.as_source()),
.map(InterpString::as_source),
Some("openai".to_string())
);
assert_eq!(
cli.exec.model.name.as_ref().map(|value| value.as_source()),
cli.exec.model.name.as_ref().map(InterpString::as_source),
Some("gpt-5".to_string())
);
assert_eq!(cli.exec.agent.permissions, Some(AgentPermissions::ReadOnly));

View file

@ -14,12 +14,12 @@ fn resolves_features_defaults_from_empty_settings() {
#[test]
fn resolves_session_sandboxes_flag() {
let settings: SettingsLayer = parse_settings_layer(
r#"
r"
_version = 1
[features]
session_sandboxes = true
"#,
",
)
.expect("fixture should parse");

View file

@ -1,6 +1,6 @@
use fabro_config::effective_settings::{EffectiveSettingsLayers, EffectiveSettingsMode};
use fabro_config::parse_settings_layer;
use fabro_types::settings::SettingsLayer;
use fabro_types::settings::{InterpString, SettingsLayer};
fn parse(source: &str) -> SettingsLayer {
parse_settings_layer(source).expect("fixture should parse")
@ -13,10 +13,10 @@ fn resolves_root_settings_defaults() {
assert_eq!(settings.project.directory, "fabro/");
assert_eq!(settings.workflow.graph, "workflow.fabro");
assert_eq!(settings.run.execution.retros, true);
assert_eq!(settings.cli.updates.check, true);
assert!(settings.run.execution.retros);
assert!(settings.cli.updates.check);
assert_eq!(settings.server.scheduler.max_concurrent_runs, 5);
assert_eq!(settings.features.session_sandboxes, false);
assert!(!settings.features.session_sandboxes);
}
#[test]
@ -100,7 +100,7 @@ name = "gpt-5"
.model
.provider
.as_ref()
.map(|value| value.as_source()),
.map(InterpString::as_source),
Some("openai".to_string())
);
assert_eq!(
@ -109,7 +109,7 @@ name = "gpt-5"
.model
.name
.as_ref()
.map(|value| value.as_source()),
.map(InterpString::as_source),
Some("gpt-5".to_string())
);
}

View file

@ -16,7 +16,7 @@ fn resolves_server_defaults_from_empty_settings() {
settings.storage.root.as_source(),
Home::from_env().storage_dir().to_string_lossy()
);
assert_eq!(settings.web.enabled, true);
assert!(settings.web.enabled);
assert_eq!(settings.web.url.as_source(), "http://localhost:3000");
assert_eq!(settings.scheduler.max_concurrent_runs, 5);

View file

@ -124,6 +124,8 @@ impl Interviewer for ControlInterviewer {
mod tests {
use std::sync::Arc;
use tokio::task;
use crate::{AnswerValue, QuestionType};
use super::*;
@ -180,7 +182,7 @@ mod tests {
let ask_interviewer = Arc::clone(&interviewer);
let ask = tokio::spawn(async move { ask_interviewer.ask(question).await });
tokio::task::yield_now().await;
task::yield_now().await;
interviewer.interrupt_all().await;
@ -208,7 +210,7 @@ mod tests {
let ask_interviewer = Arc::clone(&interviewer);
let ask = tokio::spawn(async move { ask_interviewer.ask(question).await });
tokio::task::yield_now().await;
task::yield_now().await;
interviewer.cancel_all().await;

View file

@ -482,7 +482,7 @@ mod tests {
#[test]
fn fail_closed_when_all_strategies_disabled() {
let file = settings(
r#"
r"
_version = 1
[server.auth.api.jwt]
@ -490,7 +490,7 @@ enabled = false
[server.auth.api.mtls]
enabled = false
"#,
",
);
let err =
resolve_auth_mode_with_lookup(&file, empty_lookup).expect_err("should refuse startup");
@ -1008,7 +1008,7 @@ enabled = true
avatar_url: "https://example.com/avatar.png".to_string(),
user_url: "https://github.com/brynary".to_string(),
github_id: 1,
exp: 9999999999,
exp: 9_999_999_999,
});
let response = app.oneshot(req).await.unwrap();

View file

@ -992,7 +992,7 @@ app_id = "snapshotted-app-id"
.github
.app_id
.as_ref()
.map(|value| value.as_source())
.map(fabro_types::settings::InterpString::as_source)
.as_deref(),
Some("snapshotted-app-id")
);

View file

@ -725,19 +725,19 @@ mod tests {
.as_ref()
.and_then(|server| server.storage.as_ref())
.and_then(|storage| storage.root.as_ref())
.map(|value| value.as_source());
.map(fabro_types::settings::InterpString::as_source);
assert_eq!(storage_root.as_deref(), Some("/srv/fabro-storage"));
}
#[test]
fn apply_runtime_settings_enables_web_from_cli_flag() {
let base = parse_settings(
r#"
r"
_version = 1
[server.web]
enabled = false
"#,
",
);
let args = ServeArgs {
bind: None,

View file

@ -7586,7 +7586,7 @@ level = "debug"
.model
.name
.as_ref()
.map(|value| value.as_source())
.map(fabro_types::settings::InterpString::as_source)
.as_deref(),
Some("claude-sonnet-4-5"),
);
@ -7596,7 +7596,7 @@ level = "debug"
.github
.app_id
.as_ref()
.map(|value| value.as_source())
.map(fabro_types::settings::InterpString::as_source)
.as_deref(),
Some("12345"),
);

View file

@ -793,7 +793,10 @@ mod tests {
.as_ref()
.expect("[server.integrations.github] should be present");
assert_eq!(
github.app_id.as_ref().map(|s| s.as_source()),
github
.app_id
.as_ref()
.map(fabro_types::settings::InterpString::as_source),
Some("123".to_string())
);
}

View file

@ -122,12 +122,12 @@ async fn web_enabled_serves_web_only_routes() {
#[tokio::test]
async fn web_disabled_returns_404_for_web_routes_and_keeps_machine_api() {
let settings: SettingsLayer = parse_settings_layer(
r#"
r"
_version = 1
[server.web]
enabled = false
"#,
",
)
.expect("settings fixture should parse");
let app = build_router_with_options(
@ -179,12 +179,12 @@ enabled = false
#[tokio::test]
async fn web_disabled_ignores_demo_header_dispatch() {
let settings: SettingsLayer = parse_settings_layer(
r#"
r"
_version = 1
[server.web]
enabled = false
"#,
",
)
.expect("settings fixture should parse");
let app = build_router_with_options(

View file

@ -1,3 +1,5 @@
#![allow(clippy::absolute_paths)]
mod api;
mod helpers;
mod openapi_conformance;

View file

@ -269,15 +269,14 @@ async fn cancel_at_human_gate_persists_cancelled_terminal_event() {
.as_array()
.unwrap()
.iter()
.filter_map(|event| {
(event["event"] == "run.failed").then(|| {
(
event["properties"]["reason"]
.as_str()
.map(ToOwned::to_owned),
event["properties"]["error"].as_str().map(ToOwned::to_owned),
)
})
.filter(|&event| event["event"] == "run.failed")
.map(|event| {
(
event["properties"]["reason"]
.as_str()
.map(ToOwned::to_owned),
event["properties"]["error"].as_str().map(ToOwned::to_owned),
)
})
.collect::<Vec<_>>();

View file

@ -307,7 +307,7 @@ mod tests {
let listener = TcpListener::bind("127.0.0.1:0").await.unwrap();
let addr = listener.local_addr().unwrap();
let url = format!("ws://{}", addr);
let url = format!("ws://{addr}");
let registry = registry();
let submissions = Arc::new(Mutex::new(Vec::new()));

View file

@ -276,6 +276,7 @@ fn parse_object_path(raw: &str) -> Result<ObjectPath> {
mod tests {
use super::*;
use futures::stream;
use object_store::memory::InMemory;
use fabro_types::fixtures;
@ -324,7 +325,7 @@ mod tests {
&run_id,
&node,
filename,
futures::stream::iter(vec![
stream::iter(vec![
Ok(Bytes::from_static(b"hello ")),
Ok(Bytes::from_static(b"world")),
]),

View file

@ -2,11 +2,12 @@ use std::collections::BTreeMap;
use fabro_types::graph::Graph;
use fabro_types::run_event::run::RunCreatedProps;
use fabro_types::settings::InterpString;
use fabro_types::settings::SettingsLayer;
use fabro_types::settings::run::{RunGoalLayer, RunLayer};
use fabro_types::settings::server::{
GithubIntegrationLayer, ServerIntegrationsLayer, ServerLayer, ServerStorageLayer,
};
use fabro_types::settings::{InterpString, SettingsLayer};
fn templated_settings() -> SettingsLayer {
SettingsLayer {
@ -78,7 +79,7 @@ fn run_created_props_round_trip_templated_settings() {
.as_ref()
.and_then(|server| server.storage.as_ref())
.and_then(|storage| storage.root.as_ref())
.map(|value| value.as_source()),
.map(InterpString::as_source),
Some("${env.FABRO_STORAGE}".to_string())
);
assert_eq!(
@ -89,7 +90,7 @@ fn run_created_props_round_trip_templated_settings() {
.and_then(|server| server.integrations.as_ref())
.and_then(|integrations| integrations.github.as_ref())
.and_then(|github| github.app_id.as_ref())
.map(|value| value.as_source()),
.map(InterpString::as_source),
Some("${env.GITHUB_APP_ID}".to_string())
);
}

View file

@ -4,11 +4,12 @@ use std::path::PathBuf;
use fabro_types::fixtures;
use fabro_types::graph::Graph;
use fabro_types::run::RunRecord;
use fabro_types::settings::InterpString;
use fabro_types::settings::SettingsLayer;
use fabro_types::settings::run::{RunGoalLayer, RunLayer};
use fabro_types::settings::server::{
GithubIntegrationLayer, ServerIntegrationsLayer, ServerLayer, ServerStorageLayer,
};
use fabro_types::settings::{InterpString, SettingsLayer};
fn templated_settings() -> SettingsLayer {
SettingsLayer {
@ -78,7 +79,7 @@ fn run_record_round_trips_templated_settings() {
.as_ref()
.and_then(|server| server.storage.as_ref())
.and_then(|storage| storage.root.as_ref())
.map(|value| value.as_source()),
.map(InterpString::as_source),
Some("${env.FABRO_STORAGE}".to_string())
);
assert_eq!(
@ -89,7 +90,7 @@ fn run_record_round_trips_templated_settings() {
.and_then(|server| server.integrations.as_ref())
.and_then(|integrations| integrations.github.as_ref())
.and_then(|github| github.app_id.as_ref())
.map(|value| value.as_source()),
.map(InterpString::as_source),
Some("${env.GITHUB_APP_ID}".to_string())
);
}

View file

@ -3441,7 +3441,7 @@ mod tests {
graph: serde_json::to_value(Graph::new("test")).unwrap(),
workflow_source: None,
workflow_config: None,
labels: Default::default(),
labels: BTreeMap::default(),
run_dir: "/tmp/run".to_string(),
working_directory: "/tmp/run".to_string(),
host_repo_path: None,

View file

@ -810,7 +810,7 @@ mod tests {
.model
.name
.as_ref()
.map(|value| value.as_source())
.map(fabro_types::settings::InterpString::as_source)
.as_deref(),
Some("claude-sonnet-4-6")
);
@ -820,7 +820,7 @@ mod tests {
.model
.provider
.as_ref()
.map(|value| value.as_source())
.map(fabro_types::settings::InterpString::as_source)
.as_deref(),
Some("anthropic")
);

View file

@ -1187,11 +1187,11 @@ mod tests {
PathBuf::from("children/review.fabro"),
BundledWorkflow {
logical_path: PathBuf::from("children/review.fabro"),
source: r#"digraph Review {
source: r"digraph Review {
start [shape=Mdiamond]
exit [shape=Msquare]
start -> exit
}"#
}"
.to_string(),
files: HashMap::new(),
},

View file

@ -137,9 +137,9 @@ fn load_run_checkpoint(run_dir: &Path) -> Result<Checkpoint, Box<dyn std::error:
unreachable!()
})?
};
return state
state
.checkpoint
.ok_or_else(|| "checkpoint should exist in run store".into());
.ok_or_else(|| "checkpoint should exist in run store".into())
}
async fn create_env() -> DaytonaSandbox {

View file

@ -3,6 +3,7 @@
clippy::get_unwrap,
clippy::ignore_without_reason,
clippy::items_after_statements,
clippy::large_futures,
clippy::manual_let_else,
clippy::print_stderr,
clippy::unnecessary_box_returns,
@ -169,9 +170,9 @@ fn load_run_checkpoint(run_dir: &Path) -> Result<Checkpoint, Box<dyn std::error:
unreachable!()
})?
};
return state
state
.checkpoint
.ok_or_else(|| "checkpoint should exist in run store".into());
.ok_or_else(|| "checkpoint should exist in run store".into())
}
fn save_checkpoint(path: &Path, checkpoint: &Checkpoint) {

View file

@ -1,11 +1,12 @@
use fabro_graphviz::graph::Graph;
use fabro_graphviz::parser;
use fabro_model::Catalog;
use fabro_types::settings::run::{RunGoalLayer, RunLayer, RunModelLayer, RunPullRequestLayer};
use fabro_types::settings::{InterpString, SettingsLayer};
use fabro_workflow::run_materialization::materialize_run;
fn graph(source: &str) -> Graph {
fabro_graphviz::parser::parse(source).expect("graph should parse")
parser::parse(source).expect("graph should parse")
}
#[test]
@ -32,7 +33,7 @@ fn materialize_run_applies_graph_and_catalog_defaults() {
..SettingsLayer::default()
};
let materialized = materialize_run(settings, &graph(source), &Catalog::builtin());
let materialized = materialize_run(settings, &graph(source), Catalog::builtin());
let resolved = fabro_config::resolve_run_from_file(&materialized).unwrap();
assert_eq!(
@ -40,7 +41,7 @@ fn materialize_run_applies_graph_and_catalog_defaults() {
.model
.name
.as_ref()
.map(|value| value.as_source())
.map(InterpString::as_source)
.as_deref(),
Some("claude-sonnet-4-6")
);
@ -49,7 +50,7 @@ fn materialize_run_applies_graph_and_catalog_defaults() {
.model
.provider
.as_ref()
.map(|value| value.as_source())
.map(InterpString::as_source)
.as_deref(),
Some("anthropic")
);