Enforce no-wildcard-imports via clippy workspace lint

Configure clippy `wildcard_imports = "warn"` at the workspace level and
opt all 28 crates in via `[lints] workspace = true`. Fix the three
production glob imports that triggered warnings: fabro-sandbox
read_guard, fabro-cli main, and fabro-api demo module (allowed via
attribute since it constructs many API types by design). Document the
import style convention in CLAUDE.md.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Bryan Helmkamp 2026-03-28 11:14:34 -04:00
parent 423c4b4688
commit 41e1809b21
33 changed files with 98 additions and 2 deletions

View file

@ -88,6 +88,12 @@ When working on Rust crates, read the relevant strategy doc **before** making ch
When interpolating values into shell command strings (in `fabro-exe` and `fabro-workflows`), always use the `shell_quote()` helper (backed by `shlex::try_quote`). Never use manual `replace('\'', "'\\''")` or unquoted interpolation. This applies to file paths, branch names, URLs, env vars, image names, glob patterns, and any other user-controlled input assembled into a shell script.
## Rust import style
- **Types** (structs, enums, traits): import by name — `use crate::outcome::Outcome;`
- **Functions**: import the parent module, call as `module::function()``use fabro_workflows::operations; operations::create(...)`
- **No glob imports** in production code (`use foo::*`). Globs are acceptable in test modules and preludes. Enforced by clippy `wildcard_imports` lint.
## Testing workflows
- `fabro run <name>` — run a workflow by name (resolves `fabro/workflows/<name>/workflow.toml`), e.g. `fabro run repl`

View file

@ -65,6 +65,9 @@ exec = "0.3"
slatedb = "0.11.2"
object_store = "0.12.5"
[workspace.lints.clippy]
wildcard_imports = "warn"
[profile.release]
lto = "thin"
strip = true

View file

@ -17,6 +17,9 @@ quarantine = []
[lib]
doctest = false
[lints]
workspace = true
[dependencies]
clap.workspace = true
anyhow.workspace = true

View file

@ -8,6 +8,9 @@ description = "Generated Rust types from the Fabro API OpenAPI spec"
[lib]
doctest = false
[lints]
workspace = true
[dependencies]
chrono = { workspace = true, features = ["serde"] }
serde.workspace = true

View file

@ -8,6 +8,9 @@ description = "HTTP API server for Fabro pipelines"
[lib]
doctest = false
[lints]
workspace = true
[dependencies]
fabro-config = { path = "../fabro-config", features = ["exedev"] }
fabro-graphviz = { path = "../fabro-graphviz" }

View file

@ -1,3 +1,4 @@
#[allow(clippy::wildcard_imports)]
mod demo;
pub mod error;
pub mod github_webhooks;

View file

@ -15,6 +15,9 @@ server = ["dep:fabro-api"]
exedev = ["fabro-sandbox/exe", "fabro-config/exedev", "fabro-workflows/exedev", "fabro-types/exedev"]
sleep_inhibitor = ["dep:core-foundation"]
[lints]
workspace = true
[dependencies]
fabro-config = { path = "../fabro-config" }
fabro-llm = { path = "../fabro-llm" }

View file

@ -7,7 +7,7 @@ mod shared;
mod sleep_inhibitor;
use anyhow::Result;
use args::*;
use args::{Commands, GlobalArgs, RunCommands, LONG_VERSION};
use clap::Parser;
use tracing::debug;
@ -239,6 +239,7 @@ async fn main_inner() -> (String, Result<()>) {
#[cfg(test)]
mod tests {
use super::*;
use args::{ConfigCommand, ConfigNamespace, ProviderCommand, ProviderNamespace};
use clap::Parser;
#[test]

View file

@ -13,6 +13,9 @@ default = []
exedev = ["fabro-types/exedev"]
clap = ["dep:clap", "fabro-types/clap"]
[lints]
workspace = true
[dependencies]
anyhow.workspace = true
clap = { workspace = true, optional = true }

View file

@ -8,6 +8,9 @@ description = "Generic workflow execution engine"
[lib]
doctest = false
[lints]
workspace = true
[dependencies]
async-trait.workspace = true
fabro-types = { path = "../fabro-types" }

View file

@ -8,6 +8,9 @@ description = "SQLite persistence layer for Fabro"
[lib]
doctest = false
[lints]
workspace = true
[dependencies]
sqlx = { workspace = true, features = ["sqlite"] }
chrono.workspace = true

View file

@ -8,6 +8,9 @@ description = "Parse and resolve devcontainer.json into Dockerfiles and lifecycl
[lib]
doctest = false
[lints]
workspace = true
[dependencies]
fabro-util = { path = "../fabro-util" }
serde = { workspace = true }

View file

@ -9,6 +9,9 @@ repository = "https://github.com/brynary/arc"
[lib]
doctest = false
[lints]
workspace = true
[dependencies]
git2.workspace = true
thiserror.workspace = true

View file

@ -8,6 +8,9 @@ description = "GitHub App authentication and API helpers for Fabro"
[lib]
doctest = false
[lints]
workspace = true
[dependencies]
serde.workspace = true
serde_json.workspace = true

View file

@ -8,6 +8,9 @@ description = "Graphviz DOT parser and typed graph data model"
[lib]
doctest = false
[lints]
workspace = true
[dependencies]
anyhow.workspace = true
fabro-types = { path = "../fabro-types" }

View file

@ -8,6 +8,9 @@ description = "User-defined lifecycle hooks for Fabro workflows"
[lib]
doctest = false
[lints]
workspace = true
[dependencies]
fabro-agent = { path = "../fabro-agent" }
fabro-config = { path = "../fabro-config" }

View file

@ -8,6 +8,9 @@ description = "Human-in-the-loop interviewer traits and implementations"
[lib]
doctest = false
[lints]
workspace = true
[dependencies]
serde.workspace = true
serde_json.workspace = true

View file

@ -12,6 +12,9 @@ categories = ["api-bindings"]
[lib]
doctest = false
[lints]
workspace = true
[dependencies]
anyhow.workspace = true
thiserror.workspace = true

View file

@ -8,6 +8,9 @@ description = "MCP (Model Context Protocol) client for connecting to external to
[lib]
doctest = false
[lints]
workspace = true
[dependencies]
anyhow.workspace = true
fabro-config = { path = "../fabro-config" }

View file

@ -8,6 +8,9 @@ description = "LLM model catalog: provider identity, model metadata, and resolut
[lib]
doctest = false
[lints]
workspace = true
[dependencies]
serde.workspace = true
serde_json.workspace = true

View file

@ -8,6 +8,9 @@ description = "OpenAI OAuth PKCE token acquisition for Fabro"
[lib]
doctest = false
[lints]
workspace = true
[dependencies]
serde.workspace = true
serde_json.workspace = true

View file

@ -8,6 +8,9 @@ description = "Retrospective analysis for Fabro workflow runs"
[lib]
doctest = false
[lints]
workspace = true
[dependencies]
anyhow = "1"
chrono = { workspace = true, features = ["serde"] }

View file

@ -18,6 +18,9 @@ test-support = []
[lib]
doctest = false
[lints]
workspace = true
[dependencies]
anyhow.workspace = true
async-trait.workspace = true

View file

@ -1,4 +1,4 @@
use crate::*;
use crate::Sandbox;
use std::collections::HashSet;
use std::path::{Component, PathBuf};
use std::sync::{Arc, Mutex};
@ -101,6 +101,7 @@ crate::delegate_sandbox! {
mod tests {
use super::*;
use crate::test_support::MockSandbox;
use crate::GrepOptions;
use std::collections::HashMap;
fn mock_with_files(files: HashMap<String, String>) -> MockSandbox {

View file

@ -8,6 +8,9 @@ description = "Slack Socket Mode integration for Fabro interviewer"
[lib]
doctest = false
[lints]
workspace = true
[dependencies]
fabro-interview = { path = "../fabro-interview" }
fabro-workflows = { path = "../fabro-workflows" }

View file

@ -7,6 +7,9 @@ license.workspace = true
[lib]
doctest = false
[lints]
workspace = true
[dependencies]
fabro-types = { path = "../fabro-types" }
slatedb.workspace = true

View file

@ -8,6 +8,9 @@ description = "Telemetry, analytics, and crash reporting"
[lib]
doctest = false
[lints]
workspace = true
[dependencies]
anyhow.workspace = true
base64.workspace = true

View file

@ -8,6 +8,9 @@ description = "Tracker trait and types for issue tracking integrations"
[lib]
doctest = false
[lints]
workspace = true
[dependencies]
fabro-github = { path = "../fabro-github" }
async-trait.workspace = true

View file

@ -8,6 +8,9 @@ description = "Derive macros for fabro-types"
[lib]
proc-macro = true
[lints]
workspace = true
[dependencies]
proc-macro2 = "1"
quote = "1"

View file

@ -13,6 +13,9 @@ default = []
exedev = []
clap = ["dep:clap"]
[lints]
workspace = true
[dependencies]
chrono = { workspace = true, features = ["serde"] }
clap = { workspace = true, optional = true }

View file

@ -8,6 +8,9 @@ description = "Shared utilities: secret redaction and terminal styling"
[lib]
doctest = false
[lints]
workspace = true
[dependencies]
console.workspace = true
rand.workspace = true

View file

@ -8,6 +8,9 @@ description = "Validation and lint rules for Fabro workflow graphs"
[lib]
doctest = false
[lints]
workspace = true
[dependencies]
fabro-graphviz = { path = "../fabro-graphviz" }
fabro-model = { path = "../fabro-model" }

View file

@ -16,6 +16,9 @@ doctest = false
default = []
exedev = ["fabro-sandbox/exe", "fabro-config/exedev", "fabro-types/exedev"]
[lints]
workspace = true
[dependencies]
anyhow.workspace = true
dotenvy.workspace = true