diff --git a/Cargo.toml b/Cargo.toml index c3bfef9..d8d02a2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,3 +12,15 @@ edition = "2024" authors = ["Balavignesh"] license = "MIT" repository = "https://github.com/SBALAVIGNESH123/OmniKV" + +[workspace.lints.clippy] +all = { level = "warn", priority = -1 } +pedantic = { level = "warn", priority = -1 } +nursery = { level = "warn", priority = -1 } + +[workspace.lints.rust] +dead_code = "warn" +unused_imports = "warn" +unused_mut = "warn" +unused_variables = "warn" +mismatched_lifetime_syntaxes = "warn" diff --git a/crates/omnikv-engine/Cargo.toml b/crates/omnikv-engine/Cargo.toml index 1a686d9..8dfadd1 100644 --- a/crates/omnikv-engine/Cargo.toml +++ b/crates/omnikv-engine/Cargo.toml @@ -15,6 +15,9 @@ path = "src/lib.rs" default = [] failpoints = [] +[lints] +workspace = true + [dependencies] memmap2 = "0.9.11" tokio = { version = "1.52.1", features = ["full", "macros"] } diff --git a/crates/omnikv-engine/benches/omni_bench.rs b/crates/omnikv-engine/benches/omni_bench.rs index aca5b87..c5eaae9 100644 --- a/crates/omnikv-engine/benches/omni_bench.rs +++ b/crates/omnikv-engine/benches/omni_bench.rs @@ -7,6 +7,16 @@ //! cargo bench -p omnikv-engine --bench omni_bench //! cargo bench -p omnikv-engine --bench omni_bench -- --soak 600 # 10-min soak +#![expect( + clippy::cast_possible_truncation, + clippy::cast_precision_loss, + clippy::cast_sign_loss, + clippy::doc_markdown, + clippy::too_many_lines, + clippy::uninlined_format_args, + reason = "Benchmark harness keeps readable numeric reporting and CLI output; strict clippy findings are tracked separately from production engine code." +)] + use omni_engine::{OmniKV, WriteBatch}; use std::sync::Arc; use std::sync::atomic::{AtomicBool, AtomicU64, Ordering}; diff --git a/crates/omnikv-engine/benches/scan_buffer_pool.rs b/crates/omnikv-engine/benches/scan_buffer_pool.rs index 018e871..d4c057c 100644 --- a/crates/omnikv-engine/benches/scan_buffer_pool.rs +++ b/crates/omnikv-engine/benches/scan_buffer_pool.rs @@ -8,6 +8,12 @@ //! cargo bench -p omnikv-engine --bench scan_buffer_pool //! cargo bench -p omnikv-engine --bench scan_buffer_pool -- --rows 20000 --rounds 20 +#![expect( + clippy::cast_precision_loss, + clippy::doc_markdown, + reason = "Scan benchmark keeps CLI docs and throughput math simple for before/after comparisons." +)] + use omni_engine::{OmniKV, WriteBatch}; use std::time::{Duration, Instant}; use tempfile::TempDir; diff --git a/crates/omnikv-engine/benches/volcano_dispatch.rs b/crates/omnikv-engine/benches/volcano_dispatch.rs index d71ec3e..abd879a 100644 --- a/crates/omnikv-engine/benches/volcano_dispatch.rs +++ b/crates/omnikv-engine/benches/volcano_dispatch.rs @@ -7,6 +7,13 @@ //! cargo bench -p omnikv-engine --bench volcano_dispatch //! cargo bench -p omnikv-engine --bench volcano_dispatch -- --rows 200000 --rounds 5 +#![expect( + clippy::cast_precision_loss, + clippy::doc_markdown, + clippy::missing_const_for_fn, + reason = "Dispatch benchmark favors readable throughput math and CLI documentation over style-only rewrites." +)] + use omni_engine::sql::{AggFunc, CmpOp, SelectColumn, SqlValue, WhereExpr}; use omni_engine::sql_exec::Row; use omni_engine::volcano::{ diff --git a/crates/omnikv-engine/src/lib.rs b/crates/omnikv-engine/src/lib.rs index 0b134e7..2934ee8 100644 --- a/crates/omnikv-engine/src/lib.rs +++ b/crates/omnikv-engine/src/lib.rs @@ -1,8 +1,62 @@ -#![allow(dead_code)] -#![allow(unused_imports)] -#![allow(unused_variables)] -#![allow(unused_mut)] -#![allow(mismatched_lifetime_syntaxes)] +#![expect( + dead_code, + unused_imports, + unused_variables, + reason = "Legacy modules still expose staged database features and compatibility shims; issue #64 makes this debt explicit instead of hiding it behind broad allow attributes." +)] +#![expect( + clippy::assigning_clones, + clippy::bool_to_int_with_if, + clippy::branches_sharing_code, + clippy::cast_lossless, + clippy::cast_possible_truncation, + clippy::cast_possible_wrap, + clippy::cast_precision_loss, + clippy::cast_sign_loss, + clippy::collapsible_else_if, + clippy::collection_is_never_read, + clippy::derive_partial_eq_without_eq, + clippy::doc_markdown, + clippy::explicit_iter_loop, + clippy::format_collect, + clippy::format_push_string, + clippy::if_not_else, + clippy::ignored_unit_patterns, + clippy::items_after_statements, + clippy::manual_let_else, + clippy::manual_string_new, + clippy::map_unwrap_or, + clippy::match_same_arms, + clippy::match_wildcard_for_single_variants, + clippy::missing_const_for_fn, + clippy::missing_errors_doc, + clippy::missing_panics_doc, + clippy::must_use_candidate, + clippy::needless_collect, + clippy::needless_continue, + clippy::needless_pass_by_value, + clippy::non_std_lazy_statics, + clippy::option_if_let_else, + clippy::or_fun_call, + clippy::redundant_clone, + clippy::redundant_closure_for_method_calls, + clippy::redundant_else, + clippy::self_only_used_in_recursion, + clippy::semicolon_if_nothing_returned, + clippy::significant_drop_tightening, + clippy::single_char_pattern, + clippy::single_match_else, + clippy::suboptimal_flops, + clippy::too_long_first_doc_paragraph, + clippy::too_many_lines, + clippy::uninlined_format_args, + clippy::unnecessary_wraps, + clippy::unreadable_literal, + clippy::unused_self, + clippy::use_self, + clippy::used_underscore_binding, + reason = "Strict clippy::pedantic and clippy::nursery are now enabled. These legacy findings are documented debt to burn down in focused follow-up PRs while preventing new undocumented lint categories." +)] pub mod storage { pub mod core; diff --git a/crates/omnikv-engine/src/query/optimizer.rs b/crates/omnikv-engine/src/query/optimizer.rs index d6cca08..66b69ab 100644 --- a/crates/omnikv-engine/src/query/optimizer.rs +++ b/crates/omnikv-engine/src/query/optimizer.rs @@ -9,11 +9,12 @@ //! //! The optimizer produces a `QueryPlan` tree that the executor walks. -#![allow(dead_code)] - use crate::catalog::Catalog; use crate::secondary_index::{IndexCatalog, IndexDefinition}; -use crate::sql::*; +use crate::sql::{ + CmpOp, FromClause, JoinType, OrderByItem, SelectColumn, SqlStatement, SqlValue, WhereExpr, + parse_sql, +}; use std::fmt; use std::sync::Arc; diff --git a/crates/omnikv-engine/src/query/plan_exec.rs b/crates/omnikv-engine/src/query/plan_exec.rs index a53a18e..0e84f7b 100644 --- a/crates/omnikv-engine/src/query/plan_exec.rs +++ b/crates/omnikv-engine/src/query/plan_exec.rs @@ -3,12 +3,10 @@ //! Executes queries using the optimizer's physical plan tree instead of //! the old hardcoded scan-filter-sort pipeline. -#![allow(dead_code)] - use crate::OmniKV; use crate::catalog::{Catalog, TableDef}; -use crate::optimizer::*; -use crate::sql::*; +use crate::optimizer::{AccessMethod, PlanNode}; +use crate::sql::{AggFunc, CmpOp, JoinType, OrderByItem, SelectColumn, WhereExpr}; use crate::sql_exec::Row; use std::collections::HashMap; use std::sync::{Arc, Mutex}; diff --git a/crates/omnikv-engine/src/query/sql.rs b/crates/omnikv-engine/src/query/sql.rs index 4e7e04c..7acc456 100644 --- a/crates/omnikv-engine/src/query/sql.rs +++ b/crates/omnikv-engine/src/query/sql.rs @@ -6,7 +6,10 @@ use crate::catalog::ColumnType; #[derive(Debug, Clone, PartialEq)] -#[allow(clippy::large_enum_variant)] +#[expect( + clippy::large_enum_variant, + reason = "SQL statement variants intentionally keep owned AST payloads for parser simplicity; boxing the largest variant needs a separate API-impact review." +)] pub enum SqlStatement { CreateTable { name: String, diff --git a/crates/omnikv-engine/src/query/sql_exec.rs b/crates/omnikv-engine/src/query/sql_exec.rs index 492ac6c..1670206 100644 --- a/crates/omnikv-engine/src/query/sql_exec.rs +++ b/crates/omnikv-engine/src/query/sql_exec.rs @@ -4,7 +4,10 @@ //! GROUP BY aggregation, and ORDER BY sorting. use crate::catalog::{Catalog, Column, ColumnType, TableDef}; -use crate::sql::*; +use crate::sql::{ + AggFunc, CmpOp, FromClause, JoinType, OrderByItem, SelectColumn, SetOpType, SqlColumnDef, + SqlStatement, SqlValue, WhereExpr, WindowFuncType, +}; use crate::{OmniKV, WriteBatch}; use std::collections::HashMap; use std::sync::Arc; @@ -402,7 +405,10 @@ impl SqlExecutor { .collect() } - #[allow(clippy::too_many_arguments)] + #[expect( + clippy::too_many_arguments, + reason = "The SELECT executor mirrors SQL clauses explicitly; refactoring into an execution context is planned separately to avoid query semantics churn." + )] fn exec_select( &self, columns: &[SelectColumn], @@ -674,7 +680,10 @@ impl SqlExecutor { }) } - #[allow(clippy::too_many_arguments)] + #[expect( + clippy::too_many_arguments, + reason = "Join execution keeps the parsed join shape explicit; collapsing into a context struct is a later planner cleanup." + )] fn execute_join( &self, left: &[Row], diff --git a/crates/omnikv-engine/src/query/volcano.rs b/crates/omnikv-engine/src/query/volcano.rs index 75a3ac5..501a933 100644 --- a/crates/omnikv-engine/src/query/volcano.rs +++ b/crates/omnikv-engine/src/query/volcano.rs @@ -22,12 +22,15 @@ //! SeqScanIter::next() ← reads one row at a time from storage //! ``` -#![allow(dead_code)] +#![expect( + dead_code, + reason = "The streaming executor contains staged operator variants used by benchmark and planner work that is not fully wired into the public SQL path yet." +)] use crate::OmniKV; use crate::catalog::{Catalog, TableDef}; -use crate::optimizer::*; -use crate::sql::*; +use crate::optimizer::{AccessMethod, PlanNode}; +use crate::sql::{AggFunc, CmpOp, JoinType, OrderByItem, SelectColumn, WhereExpr}; use crate::sql_exec::Row; use std::collections::HashMap; use std::sync::Arc; diff --git a/crates/omnikv-engine/src/runtime/dist_txn.rs b/crates/omnikv-engine/src/runtime/dist_txn.rs index 68476f3..aeeedef 100644 --- a/crates/omnikv-engine/src/runtime/dist_txn.rs +++ b/crates/omnikv-engine/src/runtime/dist_txn.rs @@ -482,7 +482,10 @@ struct PreparedState { /// The prepared write batch (ready to commit). batch: WriteBatch, /// Sequence at which this was prepared (for recovery). - #[allow(dead_code)] + #[expect( + dead_code, + reason = "Prepared sequence is retained for recovery/audit semantics even though the current participant tests do not read it directly yet." + )] prepare_seq: u64, /// When this was prepared. prepared_at: Instant, diff --git a/crates/omnikv-engine/src/storage/core.rs b/crates/omnikv-engine/src/storage/core.rs index 1576f75..e5e0ae5 100644 --- a/crates/omnikv-engine/src/storage/core.rs +++ b/crates/omnikv-engine/src/storage/core.rs @@ -1,8 +1,7 @@ -#![allow(dead_code)] -#![allow(unused_imports)] -#![allow(unused_variables)] -#![allow(unused_mut)] -#![allow(mismatched_lifetime_syntaxes)] +#![expect( + dead_code, + reason = "Storage core intentionally carries staged LSM, compaction, transaction, and compatibility paths while the module is being split into smaller production components." +)] use crate::{metrics_prometheus, wal}; use arc_swap::ArcSwap; diff --git a/crates/omnikv-engine/tests/anomaly_demos.rs b/crates/omnikv-engine/tests/anomaly_demos.rs index 63ec28c..8cefd6f 100644 --- a/crates/omnikv-engine/tests/anomaly_demos.rs +++ b/crates/omnikv-engine/tests/anomaly_demos.rs @@ -4,6 +4,13 @@ //! Each test sets up a scenario that would cause data corruption under //! weaker isolation levels, and verifies OmniKV detects and aborts it. +#![expect( + clippy::doc_markdown, + clippy::or_fun_call, + clippy::uninlined_format_args, + reason = "Anomaly demos intentionally read like scenario walkthroughs with generated values and human-facing assertions." +)] + use omni_engine::transaction::TransactionManager; use omni_engine::{OmniKV, WriteBatch}; use std::sync::Arc; diff --git a/crates/omnikv-engine/tests/api_error_sanitization_tests.rs b/crates/omnikv-engine/tests/api_error_sanitization_tests.rs index 04ff70f..02b5dfc 100644 --- a/crates/omnikv-engine/tests/api_error_sanitization_tests.rs +++ b/crates/omnikv-engine/tests/api_error_sanitization_tests.rs @@ -1,3 +1,10 @@ +#![expect( + clippy::doc_markdown, + clippy::match_same_arms, + clippy::uninlined_format_args, + reason = "API sanitization tests keep explicit acceptable outcomes and readable diagnostic strings." +)] + use omni_engine::{OmniError, OmniKV}; use tempfile::tempdir; diff --git a/crates/omnikv-engine/tests/benchmarks.rs b/crates/omnikv-engine/tests/benchmarks.rs index 1ceb2fd..c6fec02 100644 --- a/crates/omnikv-engine/tests/benchmarks.rs +++ b/crates/omnikv-engine/tests/benchmarks.rs @@ -11,6 +11,15 @@ //! - Transaction commit throughput (txn/sec) //! - Batch write throughput (ops/sec) +#![expect( + clippy::cast_precision_loss, + clippy::cast_sign_loss, + clippy::doc_markdown, + clippy::missing_const_for_fn, + clippy::uninlined_format_args, + reason = "Benchmark smoke tests prioritize stable, readable measurement code; strict clippy findings are documented as benchmark debt." +)] + use omni_engine::sql::{AggFunc, CmpOp, SelectColumn, SqlValue, WhereExpr}; use omni_engine::sql_exec::Row; use omni_engine::transaction::TransactionManager; diff --git a/crates/omnikv-engine/tests/concurrent_stress.rs b/crates/omnikv-engine/tests/concurrent_stress.rs index 4f8e123..3fd3c56 100644 --- a/crates/omnikv-engine/tests/concurrent_stress.rs +++ b/crates/omnikv-engine/tests/concurrent_stress.rs @@ -3,6 +3,12 @@ //! These tests prove correctness under REAL parallel thread contention — //! not simulated single-threaded scenarios. +#![expect( + clippy::or_fun_call, + clippy::uninlined_format_args, + reason = "Stress tests favor scenario clarity and repeated generated keys over style-only rewrites." +)] + use omni_engine::transaction::TransactionManager; use omni_engine::{OmniKV, WriteBatch}; use std::sync::Arc; diff --git a/crates/omnikv-engine/tests/config_tests.rs b/crates/omnikv-engine/tests/config_tests.rs index 2d1ff9d..c413a84 100644 --- a/crates/omnikv-engine/tests/config_tests.rs +++ b/crates/omnikv-engine/tests/config_tests.rs @@ -1,4 +1,8 @@ -#![allow(clippy::field_reassign_with_default)] +#![expect( + clippy::field_reassign_with_default, + clippy::redundant_closure_for_method_calls, + reason = "Config tests intentionally mutate defaults one field at a time to isolate validation failures." +)] use std::sync::Mutex; use omni_engine::config::{ diff --git a/crates/omnikv-engine/tests/crash_consistency.rs b/crates/omnikv-engine/tests/crash_consistency.rs index 465411e..c8e6433 100644 --- a/crates/omnikv-engine/tests/crash_consistency.rs +++ b/crates/omnikv-engine/tests/crash_consistency.rs @@ -1,3 +1,7 @@ +#![expect( + clippy::doc_markdown, + reason = "Crash consistency test documentation names engine files and recovery concepts directly for operator readability." +)] //! Crash-consistency tests — these tests drive the **real OmniKV engine**. //! //! Every test: diff --git a/crates/omnikv-engine/tests/debug_compaction.rs b/crates/omnikv-engine/tests/debug_compaction.rs index 6a07732..5009d2b 100644 --- a/crates/omnikv-engine/tests/debug_compaction.rs +++ b/crates/omnikv-engine/tests/debug_compaction.rs @@ -1,3 +1,8 @@ +#![expect( + clippy::uninlined_format_args, + reason = "Debug reproduction test keeps compact diagnostic formatting." +)] + use omni_engine::{OmniKV, WriteBatch}; #[test] fn test_debug_compaction() { diff --git a/crates/omnikv-engine/tests/debug_compaction_200.rs b/crates/omnikv-engine/tests/debug_compaction_200.rs index d1328f9..99160b1 100644 --- a/crates/omnikv-engine/tests/debug_compaction_200.rs +++ b/crates/omnikv-engine/tests/debug_compaction_200.rs @@ -1,3 +1,8 @@ +#![expect( + clippy::uninlined_format_args, + reason = "Debug reproduction test keeps compact diagnostic formatting." +)] + use omni_engine::{OmniKV, WriteBatch}; #[test] fn test_debug_compaction_200() { diff --git a/crates/omnikv-engine/tests/debug_reopen.rs b/crates/omnikv-engine/tests/debug_reopen.rs index d0b3b34..27a5e39 100644 --- a/crates/omnikv-engine/tests/debug_reopen.rs +++ b/crates/omnikv-engine/tests/debug_reopen.rs @@ -1,3 +1,8 @@ +#![expect( + clippy::uninlined_format_args, + reason = "Debug reproduction test keeps compact diagnostic formatting." +)] + use omni_engine::{OmniKV, WriteBatch}; #[test] fn test_debug_reopen() { diff --git a/crates/omnikv-engine/tests/durability_evidence.rs b/crates/omnikv-engine/tests/durability_evidence.rs index 9e7dff7..968603c 100644 --- a/crates/omnikv-engine/tests/durability_evidence.rs +++ b/crates/omnikv-engine/tests/durability_evidence.rs @@ -1,3 +1,10 @@ +#![expect( + clippy::cast_possible_truncation, + clippy::cast_sign_loss, + clippy::doc_markdown, + clippy::uninlined_format_args, + reason = "Durability evidence tests use generated crash-case data and compact diagnostic output to keep failure scenarios auditable." +)] /// Phase 3 — Durability Evidence Test Suite /// /// These tests prove OmniKV survives real failure scenarios: diff --git a/crates/omnikv-engine/tests/operations.rs b/crates/omnikv-engine/tests/operations.rs index d835503..13b324f 100644 --- a/crates/omnikv-engine/tests/operations.rs +++ b/crates/omnikv-engine/tests/operations.rs @@ -1,3 +1,10 @@ +#![expect( + clippy::doc_markdown, + clippy::redundant_clone, + clippy::stable_sort_primitive, + clippy::uninlined_format_args, + reason = "Operations tests keep scenario setup readable and deterministic; strict style findings are documented separately from correctness checks." +)] // ═══════════════════════════════════════════════════════════════════════════ // Operations & Edge Case Tests — Gaps #32 through #47 // ═══════════════════════════════════════════════════════════════════════════ diff --git a/crates/omnikv-engine/tests/ops_maturity.rs b/crates/omnikv-engine/tests/ops_maturity.rs index 8051937..a86f814 100644 --- a/crates/omnikv-engine/tests/ops_maturity.rs +++ b/crates/omnikv-engine/tests/ops_maturity.rs @@ -3,6 +3,13 @@ //! Tests for configuration, diagnostics, metrics, health, rate limiting, //! group commit, graceful shutdown, and crash recovery. +#![expect( + clippy::float_cmp, + clippy::significant_drop_tightening, + clippy::uninlined_format_args, + reason = "Operational maturity tests keep lock/diagnostic scopes explicit and scenario output readable." +)] + use omni_engine::hardening::{GroupCommitEngine, RateLimiter}; use omni_engine::metrics_prometheus; use omni_engine::ops::{DiagnosticReport, LogFormat, OmniConfig}; diff --git a/crates/omnikv-engine/tests/panic_policy_audit.rs b/crates/omnikv-engine/tests/panic_policy_audit.rs index 3896979..040ad6f 100644 --- a/crates/omnikv-engine/tests/panic_policy_audit.rs +++ b/crates/omnikv-engine/tests/panic_policy_audit.rs @@ -3,6 +3,15 @@ //! This test scans production `src/` files and fails if bare `.unwrap()` appears //! outside of approved locations. See docs/PANIC_POLICY.md for the full policy. +#![expect( + clippy::doc_markdown, + clippy::manual_assert, + clippy::manual_let_else, + clippy::single_match_else, + clippy::uninlined_format_args, + reason = "The audit test intentionally formats policy failures as grouped diagnostics; style cleanup is secondary to readable CI failure output." +)] + use std::fs; use std::path::Path; diff --git a/crates/omnikv-engine/tests/raft_cluster.rs b/crates/omnikv-engine/tests/raft_cluster.rs index 649b281..82ffb62 100644 --- a/crates/omnikv-engine/tests/raft_cluster.rs +++ b/crates/omnikv-engine/tests/raft_cluster.rs @@ -2,6 +2,17 @@ //! //! Proves: log replication, leader election, crash recovery across 3 nodes. +#![expect( + clippy::doc_markdown, + clippy::redundant_clone, + clippy::similar_names, + clippy::single_match_else, + clippy::too_many_lines, + clippy::uninlined_format_args, + clippy::used_underscore_binding, + reason = "Large Raft integration suite favors explicit node names, generated keys, and readable distributed-failure diagnostics." +)] + use omni_engine::OmniKV; use omni_engine::raft_storage::OmniRaftStorage; use std::sync::Arc; diff --git a/crates/omnikv-engine/tests/sql_layer.rs b/crates/omnikv-engine/tests/sql_layer.rs index 90eb7fa..007a7dd 100644 --- a/crates/omnikv-engine/tests/sql_layer.rs +++ b/crates/omnikv-engine/tests/sql_layer.rs @@ -2,6 +2,12 @@ // SQL Layer Integration Tests — Gaps #23 through #31 // ═══════════════════════════════════════════════════════════════════════════ +#![expect( + clippy::doc_markdown, + clippy::uninlined_format_args, + reason = "SQL integration tests use human-readable query labels and generated paths; style cleanup is documented separately from SQL correctness." +)] + use omni_engine::OmniKV; use omni_engine::sql::*; use omni_engine::sql_exec::*; diff --git a/crates/omnikv-engine/tests/sql_v3_features.rs b/crates/omnikv-engine/tests/sql_v3_features.rs index f5abdb9..42e5009 100644 --- a/crates/omnikv-engine/tests/sql_v3_features.rs +++ b/crates/omnikv-engine/tests/sql_v3_features.rs @@ -2,6 +2,11 @@ // SQL v3 Feature Tests — OFFSET, HAVING, Subqueries, UNION, RIGHT JOIN // ═══════════════════════════════════════════════════════════════════════════ +#![expect( + clippy::uninlined_format_args, + reason = "SQL feature tests use generated query data extensively; style-only formatting cleanup is tracked separately." +)] + use omni_engine::OmniKV; use omni_engine::sql::*; use omni_engine::sql_exec::*; diff --git a/crates/omnikv-engine/tests/storage_correctness.rs b/crates/omnikv-engine/tests/storage_correctness.rs index 15b3bbf..8e70340 100644 --- a/crates/omnikv-engine/tests/storage_correctness.rs +++ b/crates/omnikv-engine/tests/storage_correctness.rs @@ -1,3 +1,12 @@ +#![expect( + clippy::doc_markdown, + clippy::explicit_iter_loop, + clippy::many_single_char_names, + clippy::match_same_arms, + clippy::uninlined_format_args, + reason = "Storage correctness scenarios use compact generated keys and explicit loops to make crash cases auditable." +)] + /// Stage 1 — Single-node storage correctness test suite. /// /// Each test simulates a specific crash or failure point and verifies: diff --git a/crates/omnikv-engine/tests/storage_engine.rs b/crates/omnikv-engine/tests/storage_engine.rs index 1cd9ca9..ae010ae 100644 --- a/crates/omnikv-engine/tests/storage_engine.rs +++ b/crates/omnikv-engine/tests/storage_engine.rs @@ -2,6 +2,12 @@ // Storage Engine Integration Tests — Gaps #15 through #22 // ═══════════════════════════════════════════════════════════════════════════ +#![expect( + clippy::doc_markdown, + clippy::uninlined_format_args, + reason = "Storage engine integration tests use generated key names and scenario labels to keep failure output clear." +)] + use omni_engine::{OmniKV, WriteBatch}; /// Helper: create a temp OmniKV instance diff --git a/crates/omnikv-engine/tests/storage_perf.rs b/crates/omnikv-engine/tests/storage_perf.rs index ce24ff3..8e2bc12 100644 --- a/crates/omnikv-engine/tests/storage_perf.rs +++ b/crates/omnikv-engine/tests/storage_perf.rs @@ -1,6 +1,14 @@ //! Storage Performance Tests //! Validates throughput, compaction, cache, compression, and amplification. +#![expect( + clippy::cast_lossless, + clippy::cast_precision_loss, + clippy::cast_sign_loss, + clippy::uninlined_format_args, + reason = "Performance tests use compact throughput math and generated key strings for readability." +)] + use omni_engine::{OmniKV, WriteBatch}; use std::sync::Arc; use std::time::Instant; diff --git a/crates/omnikv-engine/tests/storage_tests.rs b/crates/omnikv-engine/tests/storage_tests.rs index cc9aaa8..11aa6a5 100644 --- a/crates/omnikv-engine/tests/storage_tests.rs +++ b/crates/omnikv-engine/tests/storage_tests.rs @@ -1,6 +1,14 @@ //! Integration tests for the OmniKV storage engine. //! These test the full write path, read path, compaction, TTL, MVCC, and crash recovery. +#![expect( + clippy::doc_markdown, + clippy::needless_collect, + clippy::redundant_clone, + clippy::uninlined_format_args, + reason = "Large storage integration suite favors explicit scenario setup and readable failure output; strict style cleanup is tracked separately." +)] + use omni_engine::{OmniError, OmniKV, OmniRecord, SSTableReader, SSTableWriter, WriteBatch}; use std::sync::Arc; use tempfile::TempDir; diff --git a/crates/omnikv-server/Cargo.toml b/crates/omnikv-server/Cargo.toml index a3c2cbb..f17ceab 100644 --- a/crates/omnikv-server/Cargo.toml +++ b/crates/omnikv-server/Cargo.toml @@ -34,3 +34,6 @@ tower = { version = "0.5", features = ["util"] } [[bin]] name = "omnikv-server" path = "src/main.rs" + +[lints] +workspace = true diff --git a/crates/omnikv-server/src/main.rs b/crates/omnikv-server/src/main.rs index 1c4e14a..125f3d6 100644 --- a/crates/omnikv-server/src/main.rs +++ b/crates/omnikv-server/src/main.rs @@ -6,10 +6,25 @@ //! 3. PostgreSQL wire protocol v3 (PgWire) //! 4. Prometheus metrics on /metrics -#![allow(dead_code)] -#![allow(unused_imports)] -#![allow(unused_variables)] -#![allow(unused_mut)] +#![expect( + dead_code, + unused_mut, + reason = "The server crate includes staged cluster, Raft route, and QUIC client helpers that are built in CI before every protocol surface is enabled by the binary." +)] +#![expect( + clippy::doc_markdown, + clippy::format_push_string, + clippy::ignored_unit_patterns, + clippy::items_after_statements, + clippy::manual_let_else, + clippy::match_same_arms, + clippy::missing_const_for_fn, + clippy::option_if_let_else, + clippy::single_match_else, + clippy::trait_duplication_in_bounds, + clippy::uninlined_format_args, + reason = "Strict clippy lint groups are enabled. These server style findings are documented legacy debt while protocol hardening work continues." +)] mod api; mod auth; diff --git a/crates/omnikv-server/src/raft_routes.rs b/crates/omnikv-server/src/raft_routes.rs index eece57c..f8c5b27 100644 --- a/crates/omnikv-server/src/raft_routes.rs +++ b/crates/omnikv-server/src/raft_routes.rs @@ -13,10 +13,7 @@ use axum::extract::State; use axum::response::IntoResponse; use omni_engine::raft_impl::{OmniRaft, TypeConfig}; -use openraft::raft::{ - AppendEntriesRequest, AppendEntriesResponse, InstallSnapshotRequest, InstallSnapshotResponse, - VoteRequest, VoteResponse, -}; +use openraft::raft::{AppendEntriesRequest, InstallSnapshotRequest, VoteRequest}; use std::sync::Arc; /// Shared state for Raft RPC routes. diff --git a/docs/PANIC_POLICY.md b/docs/PANIC_POLICY.md index 5646344..2777722 100644 --- a/docs/PANIC_POLICY.md +++ b/docs/PANIC_POLICY.md @@ -77,6 +77,28 @@ The `tests/panic_policy_audit.rs` test scans production source files and fails the build if bare `.unwrap()` appears outside of approved locations (tests, benchmarks, build scripts, `// SAFETY:` guarded sites). +The workspace also enables the `clippy::all`, `clippy::pedantic`, and +`clippy::nursery` lint groups through Cargo lint configuration. CI enforces the +policy with: + +```bash +cargo clippy --workspace --all-targets -- -D warnings +``` + +New lint suppressions must use `#[expect(..., reason = "...")]` instead of +`#[allow(...)]`. `expect` is intentional: CI fails when the lint no longer +triggers, which prevents stale suppressions from silently accumulating. + +Allowed clippy expectations must be narrow and justified: + +- Prefer fixing production-code lints directly when the change is low-risk. +- Use crate-level expectations only for documented legacy debt that spans many + existing call sites. +- Use item-level expectations for local invariants such as parser enum sizing, + explicit SQL clause argument lists, or test-only diagnostic formatting. +- Do not add `#[allow(...)]` in Rust source without a follow-up issue and a + specific reason this cannot be expressed as `#[expect(...)]`. + ## Adding a New Panic Before adding a new `unwrap()` or `expect()`: diff --git a/omni-client/Cargo.toml b/omni-client/Cargo.toml index 1d26507..d745460 100644 --- a/omni-client/Cargo.toml +++ b/omni-client/Cargo.toml @@ -3,6 +3,9 @@ name = "omni-client" version = "0.1.0" edition = "2021" +[lints] +workspace = true + [dependencies] reqwest = { version = "0.13", features = ["json"] } serde = { version = "1.0", features = ["derive"] } diff --git a/omni-client/src/lib.rs b/omni-client/src/lib.rs index 76f627f..c59797f 100644 --- a/omni-client/src/lib.rs +++ b/omni-client/src/lib.rs @@ -3,6 +3,19 @@ //! Production-grade Rust client for OmniKV's REST API. //! Supports CRUD, batch operations, scans, health checks, and metrics. +#![expect( + clippy::doc_markdown, + clippy::format_push_string, + clippy::map_unwrap_or, + clippy::missing_const_for_fn, + clippy::missing_errors_doc, + clippy::missing_panics_doc, + clippy::must_use_candidate, + clippy::return_self_not_must_use, + clippy::uninlined_format_args, + reason = "The published client keeps its current API surface while strict clippy groups are introduced; these documented exceptions are staged for follow-up cleanup." +)] + use reqwest::Client; use serde::{Deserialize, Serialize}; use std::time::Duration;