Skip to content

Performance

Current comparison

Assura CLI vs native LS-Lint CLI

Generated stable trees. Equivalent rules. Case definitions live on the test-case page.

Faster tool
Assura
Runtime ratio
1.62x
2x gate
Not complete
2x cases
2 / 8
Assura faster
8 / 8
Build profile
release; linux / x86_64
Hardware
AMD EPYC-Milan Processor; 16 logical CPUs
Closest case
1.27x on Web app
Floor-limited misses
0 / 6
Warm 2x gate
Complete; 8 / 8 cases
Evidence source
Commit unknown; measured worktree clean
Command
assura performance-report --output benches/history/current.json --history benches/history/ls-lint-comparison-history.jsonl --website-dir website/public/data/performance --iterations 5 --suite ls-lint
Captured
2026-07-05 15:13:56 UTC
Versions
Assura 0.3.0; ls-lint v2.3.0 native binary

Headline Case Results

One row per measured headline case. Open a case to inspect the repository shape and the policy surface behind the comparison.

Test case Project shape Runtime Result
Small library simple_library Rust/package library with docs, tests, and build output. 5 checked, 2 ignored, 4 dirs; 6 LS-Lint rules Low-end case where startup and config loading are visible. Assura CLI: 1.75 ms Native LS-Lint: 2.30 ms Assura: 1.32x 24.0% lower runtime 2x target missed (1.15 ms)
Web app web_app Frontend app with components, tests, CSS modules, assets, and dist output. 5 checked, 2 ignored, 4 dirs; 7 LS-Lint rules Common app layout with generated output pruning. Assura CLI: 2.01 ms Native LS-Lint: 2.55 ms Assura: 1.27x 21.1% lower runtime 2x target missed (1.27 ms)
Package monorepo monorepo_packages Two packages with package-local source, tests, docs, and dist output. 7 checked, 3 ignored, 10 dirs; 10 LS-Lint rules Nested package scopes without becoming a synthetic stress test. Assura CLI: 1.87 ms Native LS-Lint: 2.52 ms Assura: 1.35x 25.7% lower runtime 2x target missed (1.26 ms)
Monorepo policy monorepo_policy Strict TypeScript/Next-style workspace with app, package, docs, scripts, infra, and CI scopes. 39 checked, 10 ignored, 38 dirs; 38 LS-Lint rules Policy-shaped rules: root whitelisting, config exceptions, source bans, and generated-output pruning. Assura CLI: 2.73 ms Native LS-Lint: 4.05 ms Assura: 1.48x 32.6% lower runtime 2x target missed (2.02 ms)
Rule-heavy repo rule_heavy_repo Repo-shaped tree with many extension-specific file rules. 192 checked, 2 ignored, 9 dirs; 38 LS-Lint rules Broad LS-Lint-compatible naming surface. Assura CLI: 2.38 ms Native LS-Lint: 3.70 ms Assura: 1.55x 35.6% lower runtime 2x target missed (1.85 ms)
Generated-heavy repo ignored_generated_heavy_repo Project with large generated and coverage folders inside the tree. 2 checked, 769 ignored, 52 dirs; 2 LS-Lint rules Ignored-path pruning before validation work is spent. Assura CLI: 1.50 ms Native LS-Lint: 5.65 ms Assura: 3.77x 73.5% lower runtime 2x target met (2.83 ms)
What this does not prove yet: this checked report uses generated fixtures. Run the external-fixture command on the test-case page to produce the real-repo headline evidence.

Diagnostic Coverage

The report also keeps synthetic stress cases for regression detection. They are intentionally excluded from the headline comparison.

simple_small 51 checked, 1 ignored, 6 dirs 2 rules; directory naming plus TypeScript file naming
simple_medium 1001 checked, 1 ignored, 21 dirs 2 rules; directory naming plus TypeScript file naming
monorepo_large 5001 checked, 1 ignored, 51 dirs 2 rules; directory naming plus TypeScript file naming
rule_heavy 2001 checked, 1 ignored, 41 dirs 31 rules; directory naming plus 30 extension-specific TypeScript naming rules
ignored_generated_heavy 2 checked, 1001 ignored, 53 dirs 2 rules; directory naming, TypeScript file naming, and generated-path pruning

Assura-Native Performance

Native rows measure Assura-only capabilities that LS-Lint does not provide: content collections, graph queries, references, context packs, Markdown safe-fix dry runs, agent-query paths, session-style requests, and daemon status. These rows are diagnostic product evidence, not substitutes for the LS-Lint-equivalent cold CLI gate above.

Native report
native-current.json
Rows
150 passing rows across 6 fixtures
Evidence source
Commit 4eb5d51; source lane dirty when materialized
Captured
2026-07-05 02:08:48 UTC
Command
assura performance-report --suite native --output benches/history/native-current.json --history benches/history/native-history.jsonl --website-dir website/public/data/performance --iterations 5
Native fixture Scale Rows Slowest measured row
native small native_small 66 checked, 1 ignored, 7 dirs native content authoring matrix with 25 goals, 25 specs, 5 ADRs, Markdown links, relations, context packs, and search 25 native diagnostic rows Gate: cargo xtask native-performance-no-regression 48.0 ms native:daemon-status-cli
native medium native_medium 651 checked, 1 ignored, 7 dirs native content authoring matrix with 250 goals, 250 specs, 50 ADRs, Markdown links, relations, context packs, and search 25 native diagnostic rows Gate: cargo xtask native-performance-no-regression 149.4 ms native:daemon-status-cli
native large native_large 6501 checked, 1 ignored, 7 dirs native content authoring matrix with 2500 goals, 2500 specs, 500 ADRs, Markdown links, relations, context packs, and search 25 native diagnostic rows Gate: cargo xtask native-performance-no-regression 1635.6 ms native:daemon-status-cli
native reference heavy native_reference_heavy 651 checked, 1 ignored, 7 dirs native reference-heavy matrix with many-to-many relations, missing targets, Markdown links, and diagnostic classification 25 native diagnostic rows Gate: cargo xtask native-performance-no-regression 152.0 ms native:daemon-status-cli
native adapter mix native_adapter_mix 652 checked, 1 ignored, 8 dirs native adapter-mix matrix with Markdown frontmatter, JSON records, code-symbol references, relations, and context packs 25 native diagnostic rows Gate: cargo xtask native-performance-no-regression 141.8 ms native:daemon-status-cli
native real project native_real_project 326 checked, 1 ignored, 8 dirs native real-project shaped content authoring matrix with goals, specs, ADRs, notes, broken references, and agent-query rows 25 native diagnostic rows Gate: cargo xtask native-performance-no-regression 104.2 ms native:daemon-status-cli

Use the table above for the scoped product comparison behind the public assura check path: one Assura run versus one native LS-Lint binary run on the same repository checkout and equivalent LS-Lint-compatible ruleset. The benchmark row is named assura-cli because the measured command is the primary installable assura launcher, which routes supported one-shot assura check invocations through the lightweight checker before dispatching less common commands to assura-full. The timed command uses quiet successful validation so the comparison measures rule checking and traversal rather than JSON report serialization. The LS-Lint binary is resolved from the pinned @ls-lint/ls-lint package before timing so the measured loop does not include npm package resolution or the package’s Node wrapper.

The current checked data uses the realistic-equivalent report cohort: eight in-repo fixtures that exercise LS-Lint-compatible naming, ignore, scope, and extension behavior without requiring an external checkout cache. Pinned real-repository rows are optional extended evidence when a report is generated with the external fixture flag; they are not part of the checked report rendered on this page today.

Rows marked fixture_acceptance=accepted-ls-lint-equivalent are the enforced fixture floor. CI runs cargo xtask performance-no-slower against the checked report and fails if any accepted assura-cli fixture row is slower than the matching native ls-lint-cli row, even when aggregate numbers still look good.

The warm gate is a separate editor-session measurement. It uses a persistent assura-check-session CLI process connected to assura-checkd, so it is not a replacement for the cold one-process assura check headline path.

Assura-native rows are a second checked report, not a replacement for the LS-Lint comparison. They measure product surfaces LS-Lint does not provide: content collections, document graph queries, references, context packs, Markdown safe-fix dry runs, agent-query paths, session-style requests, and daemon status. Native rows use fixture_acceptance=assura-native-diagnostic and are protected by cargo xtask native-performance-no-regression. That gate is baseline-relative, not LS-Lint-relative: each native row carries native_regression_* metadata calibrated from the checked native baseline so reviewers can see whether the current row remains inside the expected envelope.

The post-beta LS-Lint reassessment keeps those claims separate: current accepted cold rows must be no slower than native LS-Lint row by row, while remaining 2x misses are explained through process floor, Rust CLI floor, config-load, checker-init, walk-and-validate, and report-sort phase rows.

The native suite has moved on product-path work, not just harness/reporting:

  • native_large native:phase:fact-ingest-load: 2993.6 ms -> 137.0 ms (-95.4%)
  • native_large native:phase:incremental-replace-generation: 2733.0 ms -> 118.3 ms (-95.7%)
  • native_large native:phase:object-load-validate: 236.3 ms -> 188.7 ms (-20.1%)
  • native_large native:phase:repository-validate-total: 257.7 ms -> 209.8 ms (-18.6%)

Those deltas come from the checked native history under /data/performance/native-history.jsonl, not from ad hoc local smoke runs. The remaining LS-Lint-equivalent cold miss is much narrower: the checked many_configured_scopes_regression row is already faster than native LS-Lint (14.95 ms versus 19.08 ms), but it is still not at the separate 2x target. The current cold cost on that row is concentrated in assura:phase:config-load (4.15 ms) and assura:phase:walk-and-validate (5.12 ms), so the next headline work is still product-path runtime rather than more report plumbing.

For beta, the cold LS-Lint release guardrail is row-by-row no-slower parity, not universal cold 2x. The current checked report has every accepted cold LS-Lint-equivalent fixture faster than native LS-Lint, while warm/session rows meet the 2x target across the accepted fixture set. Remaining cold 2x misses are tracked as diagnostics so they can guide future work without forcing entrypoint-specific branches or sub-millisecond tuning into the product.

Future cold optimizations must improve the ordinary public command. A change is not enough if it only helps a phase row, an in-process row, assura-check-cli, or a traversal experiment while assura check --quiet is flat or slower. The working stop/keep matrix is maintained in docs/analysis/2026-07-05-performance-decision-matrix.md.

Baseline updates are explicit source changes:

Terminal window
cargo build --release --bin assura --no-default-features --features json-output,yaml-config
cargo build --release --bin assura-full
cargo build --release -p assura-check-cli
target/release/assura performance-report \
--output benches/history/current.json \
--history benches/history/ls-lint-comparison-history.jsonl \
--website-dir website/public/data/performance \
--iterations 5

Refresh the native Assura report with:

Terminal window
cargo build --release --bin assura --no-default-features --features json-output,yaml-config
cargo build --release --bin assura-full
cargo build --release -p assura-check-cli
target/release/assura performance-report \
--suite native \
--output benches/history/native-current.json \
--history benches/history/native-history.jsonl \
--website-dir website/public/data/performance \
--iterations 5
cargo xtask native-performance-no-regression benches/history/native-current.json

Review the generated diff in benches/history/ and website/public/data/performance/ before merging.

When a checked refresh is produced from a temporary clean snapshot of a dirty source lane, also export the source provenance before running the command so the checked artifact preserves the original branch/commit/patch tuple and the fact that the source lane was dirty:

Terminal window
export ASSURA_SOURCE_COMMIT_SHA="<source-lane commit>"
export ASSURA_SOURCE_BRANCH="<source-lane branch>"
export ASSURA_SOURCE_PATCH_ID="<stable patch id for the materialized diff>"
export ASSURA_SOURCE_WORKTREE_DIRTY=true