Harden core workflows and accelerate indexing - #30
Conversation
Detect content changes that preserve metadata, retain file formatting and permissions during edits, and centralize shared project operations. Add checksummed v2 snapshots with v0.9 compatibility, bounded MCP input/output, improved audit cycle reporting, and verified release assets.
Keep the public output facade stable while separating tool renderers, path compaction, next-step guidance, value normalization, UTC formatting, and regression tests into focused modules.
Keep the public MCP API and wire contracts stable while separating server lifecycle, bounded transport, dispatch, response encoding, argument parsing, and focused tool groups. Remove legacy text rendering whose output was discarded before structured TOON encoding.
Reduce main to logging, argument parsing, and dispatcher invocation. Separate Clap types, graph/session utilities, retrieval, mutation, maintenance, watch, pipeline, and CLI regression tests while preserving command behavior and output.
Prepare parsing, word data, and trigrams with Rayon for projects of 64 or more files. Write v3 snapshots with full BLAKE3 payload hashes and hydrated search/dependency indexes while retaining v0.9-v2 readers. Add a CI performance gate requiring indexing and warm exact search to remain at least 20% faster than v0.9.0.
Replace all mutable action tags and the Rust stable branch reference with full-length commits from the official upstream repositories. Keep release labels in comments so automated and manual updates remain reviewable.
|
Warning Review limit reached
Next review available in: 26 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (8)
📝 WalkthroughWalkthroughThis PR modularizes the engine, CLI, MCP, application, snapshot, output, and audit systems; adds graph persistence and refresh behavior; preserves edit metadata; introduces installer checksums and performance gates; expands release CI; and updates tool schemas and release documentation. ChangesEngine, CLI, MCP, and Application Refactor
Release CI, Installer Checksums, and Performance Gate
Estimated code review effort: 5 (Critical) | ~120 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Only skip content verification when the filesystem change timestamp is strictly older than the snapshot. Equal timestamps can occur on coarse-resolution filesystems and must fall back to content comparison.
|
Addressed the Linux CI freshness race in 9a127ff: equal filesystem change/snapshot timestamps are now treated as ambiguous and fall back to content comparison. Added boundary coverage for older, equal, newer, and unavailable timestamps. Reran formatting, clippy with warnings denied, all 229 tests, build, and generated-doc verification successfully. |
Convert filesystem-relative paths to forward-slash project paths before indexing or watcher updates. This keeps dependency lookup and public engine paths consistent on Windows.
|
Addressed the Windows dependency failures in 2e5f4e6 by normalizing walker and watcher filesystem paths to canonical forward-slash project paths. Added a cross-platform walker regression test and reran all previously failing dependency tests plus the full suite: formatting, clippy, 230 tests, build, and generated docs all pass. |
|
CI dependency audit surfaced RUSTSEC-2026-0190 and RUSTSEC-2026-0204. Updated the lockfile to patched versions ( |
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (10)
xtask/src/main.rs (1)
141-151: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd
--lockedtocargo benchfor reproducible benchmark results.The CI pipeline uses
--lockedforcargo testandcargo build, butrun_benchomits it. Without--locked, cargo may silently update an out-of-syncCargo.lockin the baseline worktree, potentially pulling different dependency versions and skewing benchmark comparisons.♻️ Proposed fix
fn run_bench(repo_root: &Path, target_dir: &Path, filter: &str) -> Result<()> { run_command( Command::new("cargo") - .args(["bench", "--bench", "engine", "--"]) + .args(["bench", "--locked", "--bench", "engine", "--"]) .arg(filter) .arg("--noplot") .env("CARGO_TARGET_DIR", target_dir) .current_dir(repo_root), &format!("run performance benchmarks in {}", repo_root.display()), ) }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@xtask/src/main.rs` around lines 141 - 151, Update the cargo argument list in run_bench to include --locked alongside bench and the engine benchmark selection, ensuring benchmark runs use the existing Cargo.lock without modifying or resolving dependency versions..github/workflows/release.yml (1)
114-129: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick winAdd cargo caching to
test-platformsfor faster CI.The
checkandbuildjobs cache~/.cargo/registryandtarget, buttest-platformsrecompiles all dependencies from scratch on macOS and Windows. Adding the same cache step would significantly reduce CI time.♻️ Suggested cache step for test-platforms
- name: Install Rust uses: dtolnay/rust-toolchain@4be7066ada62dd38de10e7b70166bc74ed198c30 # stable + - name: Cache cargo + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 + with: + path: | + ~/.cargo/registry/index + ~/.cargo/registry/cache + ~/.cargo/git/db + target + key: ${{ runner.os }}-test-cargo-${{ hashFiles('**/Cargo.lock') }} + - name: Test run: cargo test --locked🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In @.github/workflows/release.yml around lines 114 - 129, Add a Cargo cache step to the test-platforms job, alongside its Checkout and Install Rust steps, reusing the same cache configuration and key strategy as the existing check and build jobs for ~/.cargo/registry and target. Keep the cargo test --locked command unchanged.install.ps1 (1)
50-52: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick winAdd retry logic to
Invoke-WebRequestfor transient network failures.The bash installer uses
curl --retry 3 --retry-delay 2for the SHA256SUMS download, but the PowerShell installer has no retry logic. Adding-MaximumRetryCount 3 -RetryIntervalSec 2(available in PowerShell 7+) would improve reliability for users on unstable connections.♻️ Suggested retry parameters
Invoke-WebRequest -Uri $url -OutFile $zipPath $checksumsPath = Join-Path $tmpDir "SHA256SUMS" $checksumsUrl = "https://github.com/$Repo/releases/download/$tag/SHA256SUMS" - Invoke-WebRequest -Uri $checksumsUrl -OutFile $checksumsPath + Invoke-WebRequest -Uri $checksumsUrl -OutFile $checksumsPath -MaximumRetryCount 3 -RetryIntervalSec 2If PowerShell 5.1 compatibility is required, a try-catch retry loop would be needed instead since these parameters are only available in PowerShell 7+.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@install.ps1` around lines 50 - 52, Update the Invoke-WebRequest call used to download SHA256SUMS in the checksum setup flow to retry transient failures three times with a two-second interval, using the appropriate implementation for the script’s supported PowerShell versions; preserve the existing URI and output path behavior.src/freshness.rs (1)
85-88: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick winDirectory events trigger a full project rescan each time.
seenonly dedups identical paths, so every distinct changed directory runsrefresh_project_no_rebuild(engine, root), which walks the entire project fromroot. When the watcher reports several directory events in one batch (seerefresh_from_watcherextendingevent.paths), the whole tree is re-walked N times. Metadata checks prevent double counting, but the repeated walks are wasted work.Gate the full rescan behind a one-shot flag:
let mut work = RefreshWork::default(); let mut seen = HashSet::new(); let mut refreshed_project = false;⚡ Proposed guard
if path.is_dir() { - work.add(refresh_project_no_rebuild(engine, root)?); - continue; + if !refreshed_project { + work.add(refresh_project_no_rebuild(engine, root)?); + refreshed_project = true; + } + continue; }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/freshness.rs` around lines 85 - 88, In the directory-event handling loop, add a mutable one-shot flag alongside `work` and `seen`, and only call `refresh_project_no_rebuild(engine, root)` once per refresh operation. Mark the flag after the first successful project refresh; continue deduplicating paths and processing subsequent events without repeating the full-tree scan.src/engine/context_helpers.rs (1)
18-48: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick winReplace the redundant
seenset with a key→index map
scored.iter_mut().find(...)already handles dedup/update, so the extraHashSetonly adds bookkeeping while every candidate still pays a linear scan. AHashMap<(String, String, SymbolKind, u32), usize>insrc/engine/context_helpers.rs(and the caller insrc/engine/context.rs:133) would make this path O(1) per candidate.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/engine/context_helpers.rs` around lines 18 - 48, Replace the seen HashSet parameter in push_context_symbol_candidate with a HashMap<(String, String, SymbolKind, u32), usize> and use the key to update the existing scored entry by index or append a new ScoredContextSymbol and record its index. Update the caller in the context flow to initialize and pass the map, preserving score filtering and highest-score replacement behavior while removing the linear scored.iter_mut().find scan.src/commands/retrieval.rs (1)
520-528: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low value
cmd_contextbuilds context twice; second call is dead code.
build_context_details_with_optionsis called for JSON output, thenbuild_context_with_optionsfor human-readable. Sincecli.jsonis alwaystrue(set inmain.rs), the second build is never reached. If both paths are kept for future use, consider short-circuiting to avoid the wasted computation.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/commands/retrieval.rs` around lines 520 - 528, Update cmd_context to avoid building context twice: branch on cli.json before invoking either builder, using build_context_details_with_options only for JSON output and build_context_with_options only for human-readable output. Preserve the existing print_agent_result and println! behaviors.src/commands/maintenance.rs (1)
233-267: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick winDebounce snapshot writes in
cmd_watch.Every file system event triggers a
write_snapshotcall. For rapid changes (e.g.,git checkouttouching many files), this causes excessive synchronous I/O. Consider batching changes over a short window and writing once.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/commands/maintenance.rs` around lines 233 - 267, Debounce snapshot persistence in cmd_watch instead of calling snapshot::write_snapshot immediately for every received event. Batch rapid file changes over a short window, then perform one synchronous write_snapshot call after the window expires, while preserving the existing cli.no_graph guard and warning behavior.src/cli.rs (1)
367-368: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value
structured_contentfield inMcpis dead code.
reject_removed_output_flags(called inmain.rsbeforeCli::parse()) exits with code 2 when--structured-contentor--json-outputis found anywhere in args. The field is ignored in the dispatch match (structured_content: _insrc/commands/mod.rs), so it can never influence behavior. Consider removing it to reduce confusion.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/cli.rs` around lines 367 - 368, Remove the unused structured_content field and its structured-content/json-output argument definition from the Mcp CLI arguments in the relevant command declaration. Update the dispatch pattern in the command handling code to stop matching or ignoring structured_content, while preserving reject_removed_output_flags as the sole handling for those removed flags.src/output/mod.rs (1)
55-93: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winConsider deduplicating
search_result_path_facetsandword_result_path_facets.These two functions are identical except for the input type. A shared helper accepting an iterator of path strings would eliminate the duplication.
♻️ Proposed refactor
pub fn search_result_path_facets(results: &[SearchResult]) -> Value { - let mut counts = BTreeMap::<String, usize>::new(); - for result in results { - let prefix = result - .path - .split('/') - .next() - .filter(|prefix| !prefix.is_empty()) - .unwrap_or("."); - *counts.entry(prefix.to_string()).or_default() += 1; - } - - Value::Array( - counts - .into_iter() - .map(|(path_prefix, count)| json!({ "path_prefix": path_prefix, "count": count })) - .collect(), - ) + path_prefix_facets(results.iter().map(|r| r.path.as_str())) } pub fn word_result_path_facets(results: &[WordSearchResult]) -> Value { - let mut counts = BTreeMap::<String, usize>::new(); - for result in results { - let prefix = result - .path - .split('/') - .next() - .filter(|prefix| !prefix.is_empty()) - .unwrap_or("."); - *counts.entry(prefix.to_string()).or_default() += 1; - } - - Value::Array( - counts - .into_iter() - .map(|(path_prefix, count)| json!({ "path_prefix": path_prefix, "count": count })) - .collect(), - ) + path_prefix_facets(results.iter().map(|r| r.path.as_str())) +} + +fn path_prefix_facets<'a>(paths: impl IntoIterator<Item = &'a str>) -> Value { + let mut counts = BTreeMap::<String, usize>::new(); + for path in paths { + let prefix = path + .split('/') + .next() + .filter(|prefix| !prefix.is_empty()) + .unwrap_or("."); + *counts.entry(prefix.to_string()).or_default() += 1; + } + Value::Array( + counts + .into_iter() + .map(|(path_prefix, count)| json!({ "path_prefix": path_prefix, "count": count })) + .collect(), + ) }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/output/mod.rs` around lines 55 - 93, Deduplicate the identical counting logic in search_result_path_facets and word_result_path_facets by introducing a shared helper that accepts an iterator of path strings and returns the facet Value. Update both public functions to pass their results’ path values to this helper while preserving the existing prefix handling, counting, ordering, and JSON structure.src/mcp/dispatch.rs (1)
8-8: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winExtract
MAX_RETRIEVAL_RESULTSto a shared location.This constant is also defined as
200insrc/mcp/retrieval.rs:13, andtool_globinretrieval.rs:85hardcodes200usizeas a third source. If the limit changes in one place, the others won't follow, causing inconsistent clamping across tools.Consider defining it once (e.g., in
mod.rsor a shared constants module) and importing it in bothdispatch.rsandretrieval.rs.♻️ Suggested consolidation
// In src/mcp/mod.rs, add: + pub(super) const MAX_RETRIEVAL_RESULTS: usize = 200; // In src/mcp/dispatch.rs: - const MAX_RETRIEVAL_RESULTS: usize = 200; + use super::MAX_RETRIEVAL_RESULTS; // In src/mcp/retrieval.rs: - const MAX_RETRIEVAL_RESULTS: usize = 200; + use super::MAX_RETRIEVAL_RESULTS; // In src/mcp/retrieval.rs tool_glob: - let max = 200usize; + let max = MAX_RETRIEVAL_RESULTS;🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/mcp/dispatch.rs` at line 8, Define MAX_RETRIEVAL_RESULTS once in a shared MCP location, then import and use it from dispatch.rs and retrieval.rs. Replace retrieval.rs’s duplicate constant and tool_glob’s hardcoded 200usize with the shared symbol, preserving the existing limit of 200 for all clamping paths.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/release.yml:
- Around line 122-123: Update the Checkout steps in both the test-platforms and
github-release jobs to set persist-credentials to false. Leave the existing
checkout action references and subsequent job behavior unchanged.
In `@src/commands/maintenance.rs`:
- Around line 175-186: Update cmd_audit before the strict failure path to
explicitly flush stdout after rendering the audit report and before
std::process::exit(1). Preserve the existing report output and exit behavior,
propagating any flush error consistently with the function’s Result return.
In `@src/commands/retrieval.rs`:
- Around line 15-21: Update cmd_search’s search_rich error branch to emit the
same structured JSON error response on stdout used by cmd_read and cmd_outline,
rather than printing to stderr and returning an empty success. Preserve the
existing successful results path and ensure failures remain represented
consistently for JSON consumers.
In `@src/edit.rs`:
- Around line 465-476: Update the temporary-file write closure around
file.write_all so permissions are applied immediately after the temp file is
created and before any content is written. Move the existing set_permissions
call ahead of write_all while preserving existing_permissions handling and its
contextual error message; leave the final sync behavior unchanged.
In `@src/mcp/mutation.rs`:
- Around line 34-44: Add the compact field to the unchanged response constructed
in the result.unchanged branch of the mutation handler, using the existing
compact value so its response shape matches the normal response while preserving
all other fields and behavior.
---
Nitpick comments:
In @.github/workflows/release.yml:
- Around line 114-129: Add a Cargo cache step to the test-platforms job,
alongside its Checkout and Install Rust steps, reusing the same cache
configuration and key strategy as the existing check and build jobs for
~/.cargo/registry and target. Keep the cargo test --locked command unchanged.
In `@install.ps1`:
- Around line 50-52: Update the Invoke-WebRequest call used to download
SHA256SUMS in the checksum setup flow to retry transient failures three times
with a two-second interval, using the appropriate implementation for the
script’s supported PowerShell versions; preserve the existing URI and output
path behavior.
In `@src/cli.rs`:
- Around line 367-368: Remove the unused structured_content field and its
structured-content/json-output argument definition from the Mcp CLI arguments in
the relevant command declaration. Update the dispatch pattern in the command
handling code to stop matching or ignoring structured_content, while preserving
reject_removed_output_flags as the sole handling for those removed flags.
In `@src/commands/maintenance.rs`:
- Around line 233-267: Debounce snapshot persistence in cmd_watch instead of
calling snapshot::write_snapshot immediately for every received event. Batch
rapid file changes over a short window, then perform one synchronous
write_snapshot call after the window expires, while preserving the existing
cli.no_graph guard and warning behavior.
In `@src/commands/retrieval.rs`:
- Around line 520-528: Update cmd_context to avoid building context twice:
branch on cli.json before invoking either builder, using
build_context_details_with_options only for JSON output and
build_context_with_options only for human-readable output. Preserve the existing
print_agent_result and println! behaviors.
In `@src/engine/context_helpers.rs`:
- Around line 18-48: Replace the seen HashSet parameter in
push_context_symbol_candidate with a HashMap<(String, String, SymbolKind, u32),
usize> and use the key to update the existing scored entry by index or append a
new ScoredContextSymbol and record its index. Update the caller in the context
flow to initialize and pass the map, preserving score filtering and
highest-score replacement behavior while removing the linear
scored.iter_mut().find scan.
In `@src/freshness.rs`:
- Around line 85-88: In the directory-event handling loop, add a mutable
one-shot flag alongside `work` and `seen`, and only call
`refresh_project_no_rebuild(engine, root)` once per refresh operation. Mark the
flag after the first successful project refresh; continue deduplicating paths
and processing subsequent events without repeating the full-tree scan.
In `@src/mcp/dispatch.rs`:
- Line 8: Define MAX_RETRIEVAL_RESULTS once in a shared MCP location, then
import and use it from dispatch.rs and retrieval.rs. Replace retrieval.rs’s
duplicate constant and tool_glob’s hardcoded 200usize with the shared symbol,
preserving the existing limit of 200 for all clamping paths.
In `@src/output/mod.rs`:
- Around line 55-93: Deduplicate the identical counting logic in
search_result_path_facets and word_result_path_facets by introducing a shared
helper that accepts an iterator of path strings and returns the facet Value.
Update both public functions to pass their results’ path values to this helper
while preserving the existing prefix handling, counting, ordering, and JSON
structure.
In `@xtask/src/main.rs`:
- Around line 141-151: Update the cargo argument list in run_bench to include
--locked alongside bench and the engine benchmark selection, ensuring benchmark
runs use the existing Cargo.lock without modifying or resolving dependency
versions.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 4adbdc31-c2e4-47e3-9456-0ea5bc178a24
⛔ Files ignored due to path filters (1)
Cargo.lockis excluded by!**/*.lock
📒 Files selected for processing (69)
.cargo/audit.toml.github/workflows/release.ymlCHANGELOG.mdCargo.tomlbenches/engine.rsdocs/install.mddocs/tools.mdinstall.ps1install.shjustfilesrc/application.rssrc/audit.rssrc/audit/config.rssrc/audit/rules.rssrc/audit/rules/architecture.rssrc/audit/rules/dead_code.rssrc/cache.rssrc/cli.rssrc/cli_tests.rssrc/cli_upgrade.rssrc/commands/graph.rssrc/commands/maintenance.rssrc/commands/mod.rssrc/commands/mutation.rssrc/commands/retrieval.rssrc/commands/shared.rssrc/edit.rssrc/engine/context.rssrc/engine/context_helpers.rssrc/engine/core.rssrc/engine/dep_graph.rssrc/engine/files.rssrc/engine/indexing.rssrc/engine/mod.rssrc/engine/persistence.rssrc/engine/search.rssrc/engine/shared.rssrc/engine/tests.rssrc/freshness.rssrc/index/symbol.rssrc/index/trigram.rssrc/index/word.rssrc/lib.rssrc/main.rssrc/mcp.rssrc/mcp/args.rssrc/mcp/diagnostics.rssrc/mcp/dispatch.rssrc/mcp/maintenance.rssrc/mcp/mod.rssrc/mcp/mutation.rssrc/mcp/response.rssrc/mcp/retrieval.rssrc/mcp/server.rssrc/mcp/tests.rssrc/mcp/tool_spec.rssrc/mcp/transport.rssrc/output.rssrc/output/compact.rssrc/output/guidance.rssrc/output/mod.rssrc/output/renderers.rssrc/output/tests.rssrc/output/time.rssrc/output/value.rssrc/snapshot.rssrc/types.rssrc/walker.rsxtask/src/main.rs
💤 Files with no reviewable changes (3)
- src/cache.rs
- src/output.rs
- src/mcp.rs
|
The refreshed audit passed. CI then surfaced ShellCheck SC2016 on an intentionally literal |
|
Addressed all five actionable review threads in 9fbc708 and resolved them after verification. Local gate: fmt, clippy with warnings denied, 231 tests/bench targets, build, generated-doc sync, installer syntax, workflow YAML, and diff checks all pass. |
Summary
Compatibility and assumptions
lexa::engine::*, CLI, and MCP behavior is preserved unless explicitly hardenedbincoderemains read-only for legacy snapshot compatibilityVerification
cargo fmt --all -- --checkcargo clippy --workspace --all-targets --all-features -- -D warningscargo test --locked— 228 tests passedcargo build --lockedcargo run -p xtask -- gen-skill --checkcargo run -p xtask -- perf-gatesh -n install.shLocal limitations
shellcheckand PowerShell (pwsh) were not installed locally; the configured CI jobs cover those checks.Summary by CodeRabbit
New Features
Bug Fixes