lessence 0.4.1

Extract the essence of your logs — compress repetitive lines while preserving all unique information
Documentation
[package]
name = "lessence"
version = "0.4.1"
edition = "2024"
rust-version = "1.90"
description = "Extract the essence of your logs — compress repetitive lines while preserving all unique information"
license = "MIT"
repository = "https://github.com/air-gapped/lessence"
readme = "README.md"
keywords = ["log-compression", "cli", "log-analysis", "devops", "deduplication"]
categories = ["command-line-utilities", "text-processing"]
autobenches = false
autotests = false
exclude = [".github/", ".ideas/", ".claude/", "examples/", "tests/", "benches/"]

[[bin]]
name = "lessence"
path = "src/main.rs"
test = false  # lib tests already cover everything; avoids 161 duplicate test runs

[dependencies]
regex = "1.10"
mutants = "0.0.4"
clap = { version = "4.6", features = ["derive"] }
clap_complete = "4"
anyhow = "1.0"
chrono = { version = "0.4", default-features = false, features = ["clock"] }
ahash = "0.8"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
rayon = "1.12.0"
terminal_size = "0.4.4"
# Deterministic, cross-platform seeded sampling for rollup metadata.
# rand_chacha is explicitly portable (ChaCha8Rng gives the same sequence
# from the same seed on Linux, macOS, and Windows) — unlike SmallRng,
# which picks the fastest underlying generator per platform and is NOT
# stable across them. Determinism is load-bearing for snapshot tests
# and agent-cacheable outputs; performance is irrelevant here because
# we draw at most K samples per group, not per line.
#
# Keep default-features enabled: the `alloc` feature (on by default) is
# what gates `IndexedRandom::choose_multiple`, and we deliberately skip
# pulling in rand_core for thread-local RNGs we don't use.
#
# Pinned to 0.9, not 0.10, on purpose. Revisit only when one of the
# "when to migrate" conditions below is true:
#   - A security advisory lands against 0.9.x (RUSTSEC-2026-0097 is
#     already fixed in 0.9.3 and does not affect our seeded use anyway).
#   - The 0.9 line stops receiving patch releases.
#   - We need something 0.10 adds (unlikely — our surface is two calls).
# Why not now:
#   - rand 0.10 only promises stream stability for StdRng, not for
#     ChaCha8Rng (now a re-export from the `chacha20` crate under a
#     `chacha` feature). The sampler was also renamed `choose_multiple`
#     → `sample` in the same release. Either of those could shift the
#     exact draw without any compile error, silently re-baselining every
#     insta snapshot touching rollup metadata and invalidating agent
#     caches keyed on output. The determinism contract above is the
#     whole reason we use this crate, so drift here is a regression
#     even when it "still works".
#   - rand and rand_chacha must be bumped together (separate PRs hit
#     two-copies-of-rand_core and fail to compile — see closed PRs #33
#     and #38). Dependabot is grouped + 0.10-major-ignored accordingly
#     in .github/dependabot.yml.
rand = { version = "0.9", default-features = false, features = ["alloc"] }
rand_chacha = "0.9"

[dev-dependencies]
criterion = { version = "0.8", features = ["html_reports"] }
tempfile = "3.0"
toml = "1.1"
regex = "1.10"
insta = "1"
proptest = "1"

# Consolidated test binaries (5 barrels instead of 40 separate binaries).
# Each barrel imports submodules — one link step per category.
# See: https://matklad.github.io/2021/02/27/delete-cargo-integration-tests.html
[[test]]
name = "integration"
path = "tests/integration.rs"

[[test]]
name = "contract"
path = "tests/contract.rs"

[[test]]
name = "unit"
path = "tests/unit.rs"

[[test]]
name = "security"
path = "tests/security.rs"

[[test]]
name = "misc"
path = "tests/misc.rs"

# Criterion benchmarks — perf gate for the structured-folding-output feature.
# See docs/bench.md for how to record and compare baselines.
# Files in examples/ are gitignored; benches skip gracefully when missing.
[[bench]]
name = "folder_e2e"
harness = false

[[bench]]
name = "folder_streaming_only"
harness = false

[[bench]]
name = "folder_parallel_e2e"
harness = false

[[bench]]
name = "normalize_line"
harness = false

# Phase 5 calibration harness — not a criterion bench, a one-shot
# binary that measures per-group distinct_count distributions across
# the corpus and recommends values for the three PLACEHOLDER_* constants.
[[bench]]
name = "calibrate_rollup"
harness = false

[lints.clippy]
pedantic = { level = "warn", priority = -1 }
# Selectively allow noisy pedantic lints
module_name_repetitions = "allow"
must_use_candidate = "allow"
missing_errors_doc = "allow"
missing_panics_doc = "allow"
items_after_statements = "allow"
cast_possible_truncation = "allow"
cast_precision_loss = "allow"
cast_sign_loss = "allow"
struct_excessive_bools = "allow"
similar_names = "allow"
too_many_lines = "allow"
doc_markdown = "allow"
unnecessary_wraps = "allow"
unused_self = "allow"
case_sensitive_file_extension_comparisons = "allow"
match_same_arms = "allow"
manual_split_once = "allow"
ignored_unit_patterns = "allow"
wildcard_in_or_patterns = "allow"
cast_possible_wrap = "allow"
needless_bool = "allow"
format_push_string = "allow"
manual_strip = "allow"
if_not_else = "allow"
match_wild_err_arm = "allow"
# Warnings we want to enforce
needless_pass_by_value = "warn"

[lints.rust]
unsafe_code = "forbid"

[package.metadata.binstall]
pkg-url = "{ repo }/releases/download/v{ version }/{ name }-{ target }{ archive-suffix }"
bin-dir = "{ bin }{ binary-ext }"
pkg-fmt = "tgz"

[package.metadata.binstall.overrides.x86_64-pc-windows-msvc]
pkg-fmt = "zip"

[profile.release]
lto = true
codegen-units = 1
panic = "abort"
strip = true

[profile.bench]
debug = true

# Faster test execution in debug mode. opt-level=1 recovers 3-5x runtime
# vs opt-level=0 for CPU-bound regex/normalization code, with only ~15%
# longer compile times.
[profile.test]
opt-level = 1

# Custom profile for cargo-mutants: fast execution + fast incremental builds.
# Used via `cargo mutants --profile mutants` or .cargo/mutants.toml.
[profile.mutants]
inherits = "test"
opt-level = 1
debug = "none"