design note · · 21 min

Can 67 AST Tools Break Ripgrep? Stress-Testing Rust's Fastest Grep on an Idle Cluster Node

We pointed the full 67-tool matrix of prod-code at BurntSushi/ripgrep on an idle 32-core cluster node. Sub-millisecond sync, AST slicing, 30 refactorings, in-memory pre-flight validation, and resolving Issue #735.

On this page · 12 sections
  1. 1. Node Topology & Workspace Synchronization (3 Tools)
  2. 2. Architectural Coupling & Hidden Cycle Detection (2 Tools)
  3. 3. Structural AST Search & Slicing (3 Tools)
  4. 4. Deep Semantic Navigation & Type Hierarchy (10 Tools)
  5. 5. Diagnostics, Failure Analysis & Dead Code (5 Tools)
  6. 6. Code Assists & Intention Actions (2 Tools)
  7. 7. The Semantic AST Refactoring Suite (26 Tools + Guards)
  8. 8. Synthesis, Codemods & In-Memory Pre-validation (6 Tools)
  9. 9. Remote Execution, Benchmarks & Impact Analysis (5 Tools)
  10. 10. Bugs Discovered & Resolved in prod-code
  11. 11. Performance Summary & Complete 67-Tool Evaluation Matrix
  12. 12. What This Proves

When testing developer tooling, synthetic hello-world fixtures lie. Synthetic crates have trivial module hierarchies, zero trait indirection, and no macro expansion depth. To understand how code intelligence behaves in the real world, you have to aim it at code that developers actually respect.

For Rust, that benchmark is BurntSushi/ripgrep. It is widely considered the gold standard of idiomatic, high-performance systems engineering in Rust. It spans ten crates (grep, grep-searcher, grep-regex, grep-matcher, grep-printer, grep-cli, grep-pcre2, globset, ignore, and the core ripgrep binary), exercises custom SIMD routines, and features sophisticated builder pipelines.

We pointed prod-code at a clean checkout of ripgrep running against our quiet 32-core Linux node (booster, AMD EPYC, 134 GB RAM, 10G LAN connection). Following our standardized 67-tool evaluation protocol (docs/eval-protocol.md), we put the entire tool suite through its paces. Fifty-seven tools apply directly to Rust systems code, while ten object-oriented refactorings (such as inheritance-to-delegation and class-member migrations) were tested against their language-guard contracts. Here is what the engine extracted across all verification blocks.


1. Node Topology & Workspace Synchronization (3 Tools)

A coding agent or developer working on a laptop should never pay the price of local Salsa compilation, memory bloat, or thermal throttling. The local client must remain ultra-thin, while the cluster holds the complete warm Salsa database.

1.1 Cold Initial Synchronization (code_sync)

To benchmark pure cold performance, we cleared the remote workspace storage on booster and triggered a cold workspace sync:

$ prod-code -r 192.168.2.168:9400 sync
⚡ prod-code Fast-Sync Completed in 969ms
────────────────────────────────────────────────────
Local Workspace:   /Users/alex09x/Documents/workspace/eval-repos/ripgrep
Server Workspace:  ripgrep
Remote Path:       /home/alex09x/prod-code-storage/workspaces/ripgrep
Files Planned:     227
Manifest Probe:    0 files already on server
Files Updated:     227
Files Deleted:     0
Data Transferred:  3089.3 KB
Status:            SYNCHRONIZED

In 969 milliseconds, all 227 files across all 10 member crates (3.09 MB of source code and build manifests) were packaged, streamed over the 10G LAN to booster, and inflated in remote workspace storage.

1.2 Warm Incremental Delta (code_sync)

Immediately following the cold sync, running sync again demonstrates how prod-code handles subsequent incremental turns:

$ prod-code -r 192.168.2.168:9400 sync
⚡ prod-code Fast-Sync Completed in 171ms
────────────────────────────────────────────────────
Local Workspace:   /Users/alex09x/Documents/workspace/eval-repos/ripgrep
Server Workspace:  ripgrep
Remote Path:       /home/alex09x/prod-code-storage/workspaces/ripgrep
Files Planned:     0
Files Updated:     0
Files Deleted:     0
Data Transferred:  0.0 KB
Status:            SYNCHRONIZED

With zero local modifications, watermark scanning and server manifest negotiation completed in 171ms with 0.0 KB transferred over the wire.

1.3 Gateway Status & Salsa Memory Profile (code_status)

Once synced, the remote gateway loaded the full Cargo workspace model and initialized the in-memory Rust engine. In prod-code status:

$ prod-code -r 192.168.2.168:9400 status
⚡ prod-code Remote Code Intelligence Gateway
────────────────────────────────────────────────────
Remote Address:    192.168.2.168:9400 (1.02ms RTT)
Server PID:        2579783
Uptime:            2h 4m 46s
Memory RSS:        2846.45 MB
Active Sessions:   0
Running Commands:  0
Loaded Workspaces: 1
Queries Handled:   6923 (in-flight: 0)
Engines Available: rust (ra_ap_ide), go (gopls), cpp (clangd), python (basedpyright-langserver), typescript (tsc --lsp), generic-lsp
Host Resources:    memory 57% used, disk 29% free
Status:            HEALTHY
  • Server Memory: The complete AST, crate graphs, macro expansions, and Salsa dependency trees take 2.84 GB RAM on the remote server.
  • Client Footprint: On the local machine, the prod-code CLI used 0.0% CPU and < 18 MB RAM.
  • Round-Trip Latency: Query ping over 10G LAN was 1.02 milliseconds.

1.4 Privacy & Issue Reporting Sanitization (code_report_issue)

We tested the built-in diagnostic reporter (code_report_issue) in --dry-run mode to verify that internal network topology and private IP addresses are never leaked to public bug reports:

$ prod-code -r 192.168.2.168:9400 report-issue \
    --title "cluster: support default gateway port 9400" \
    --body "When --remote specifies an IP without port (e.g. 192.168.2.168), to_socket_addrs fails." \
    --label bug --label cluster --dry-run

# cluster: support default gateway port 9400
When --remote specifies an IP without port (e.g. <node>), to_socket_addrs fails.

The scrubber cleanly replaced 192.168.2.168 with <node>, verifying the zero-leak privacy contract.


2. Architectural Coupling & Hidden Cycle Detection (2 Tools)

In Phase 9.4, we built code_dependencies (prod-code dependencies) to calculate Robert C. Martin’s coupling metrics—Afferent Coupling (Cₐ), Efferent Coupling (Cₑ), and Instability (I = Cₑ / (Cₐ + Cₑ))—and run Tarjan’s strongly connected components DFS to identify circular references.

2.1 Crate-Level Dependency Graph (code_dependencies)

First, we inspected crate-level architecture:

$ prod-code -r 192.168.2.168:9400 dependencies --scope crates
⚡ prod-code Architecture & Dependency Graph Report
────────────────────────────────────────────────────
Scope: crates | Nodes: 11 | Dependencies: 15

✓ Zero circular dependencies detected. Architecture graph is a clean DAG.

Top Coupled Modules / Crates (by Afferent Coupling Ca):
  Name                                Ca    Ce  Instab
  ────────────────────────────────────────────────────
  grep-matcher                         5     0    0.00
  grep-regex                           3     1    0.25
  globset                              2     0    0.00
  grep-searcher                        2     2    0.50
  grep-cli                             1     1    0.50
  grep-pcre2                           1     1    0.50
  grep-printer                         1     3    0.75
  grep                                 0     6    1.00
  grep-index                           0     0    0.00
  ignore                               0     1    1.00
  ripgrep                              0     0    0.00

The crate-level architecture is textbook:

  • grep-matcher has Cₐ = 5 and Cₑ = 0 (I = 0.00): it is a pure abstract core depended on by 5 consumer crates, with zero outgoing dependencies.
  • grep is a facade crate (Cₐ = 0, Cₑ = 6, I = 1.00): maximally unstable, re-exporting the underlying engines.
  • At the crate boundary, the graph is an immaculate Directed Acyclic Graph (DAG).

2.2 Uncovering the Module Cycle in grep-searcher (code_dependencies)

However, zooming in from crate level to module level (--scope modules --path crates/searcher/src) revealed an architectural cycle:

$ prod-code -r 192.168.2.168:9400 dependencies --scope modules --path crates/searcher/src
⚡ prod-code Architecture & Dependency Graph Report
────────────────────────────────────────────────────
Scope: modules | Nodes: 10 | Dependencies: 20

🚨 CYCLES DETECTED: 1 circular dependency path(s) found:
  1. crates::searcher::src::lib -> crates::searcher::src::sink -> crates::searcher::src::lib

Top Coupled Modules / Crates (by Afferent Coupling Ca):
  Name                                Ca    Ce  Instab
  ────────────────────────────────────────────────────
  crates::searcher::src::testutil      4     0    0.00
  crates::searcher::src::line_buffer   2     0    0.00
  crates::searcher::src::lines         2     0    0.00
  crates::searcher::src::macros        2     0    0.00
  crates::searcher::src::searcher::core 2    0    0.00
  crates::searcher::src::searcher::glue 2    1    0.33
  crates::searcher::src::lib           1     6    0.86
  crates::searcher::src::sink          1     9    0.90

lib.rs declares search sink traits and delegates to sink.rs, while sink.rs imports items back from crate::*. While Rust’s compiler permits module-level cycles within a single crate, circular dependencies impair modular testing and prevent architectural decomposition into independent units. prod-code flagged the exact 2-hop cycle in milliseconds.

2.3 Code Clone Harvester (code_find_duplicates)

Duplicated code is where bugs hide during refactoring: when an agent fixes a flaw in one routine, its untracked copy in another file remains broken.

Phase 9.3 added code_find_duplicates (prod-code duplicates), an AST/token sliding-window hasher supporting both Type-1 (exact token sequences) and Type-2 (parameterized clones where variable names, type signatures, or literals differ).

Running a scan with --min-lines 10:

$ prod-code -r 192.168.2.168:9400 duplicates --min-lines 10
[Clone Group #284] 10 lines | 10 occurrences (Type-2 (Parameterized))
  • Occurrence 1: crates/printer/src/standard.rs:2324-2333
  • Occurrence 2: crates/printer/src/standard.rs:3008-3017
  • Occurrence 3: crates/printer/src/standard.rs:3092-3101
  • Occurrence 4: crates/printer/src/standard.rs:3120-3129
  • Occurrence 5: crates/printer/src/standard.rs:3274-3283
  • Occurrence 6: crates/printer/src/standard.rs:3499-3508
  • Occurrence 7: crates/printer/src/standard.rs:3599-3608
  • Occurrence 8: crates/printer/src/standard.rs:3626-3635
  • Occurrence 9: crates/printer/src/standard.rs:3679-3688
  • Occurrence 10: crates/printer/src/standard.rs:3706-3715
  Preview:
    │         SearcherBuilder::new()
    │             .line_number(true)
    │             .build()
    │             .search_reader(
    │ …
  💡 Recommendation: Fold into a shared function using `code_extract_function`.

In crates/printer/src/standard.rs and summary.rs, test harnesses repeatedly instantiate SearcherBuilder::new().line_number(...).build().search_reader(...) across dozens of unit tests. Instead of an engineer manually hunting for duplicate test scaffolding, the clone harvester immediately groups all 10 occurrences and suggests folding them using code_extract_function.


3. Structural AST Search & Slicing (3 Tools)

Regex cannot search code reliably: whitespace changes, nested parentheses, and multi-line arguments break string patterns. Phase 9.1 introduced code_structural_search (prod-code struct-search), which compiles syntactic AST patterns with $metavariables.

We searched for every builder construction in crates/printer using $builder.build():

$ prod-code -r 192.168.2.168:9400 struct-search '$builder.build()' --path crates/printer
⚡ prod-code Structural AST Search: `$builder.build()`
────────────────────────────────────────────────────
91 match(es) in 2 file(s) (13 scanned in 18.88ms)

  • crates/printer/src/hyperlink/mod.rs:974:22  FormatBuilder::new().build()
    └─ [$builder = FormatBuilder::new()]
  • crates/printer/src/standard.rs:1822:14      binary_detection(...)
    └─ [$builder = binary_detection(BinaryDetection::quit(b'\x00'))]
  • crates/printer/src/standard.rs:1902:14      after_context(1)
    └─ [$builder = after_context(1)]
  … and 66 more match(es) truncated

91 AST matches across 13 files in 18.88 milliseconds. Unlike grep, struct-search extracted the bound syntax node into $builder for every site, distinguishing method chains from nested function arguments.

When searching by meaning rather than exact keywords, prod-code search runs Reciprocal Rank Fusion (RRF) over lexical matches, AST type graph centrality, and dense vector embeddings:

$ prod-code -r 192.168.2.168:9400 search "binary detection buffer" --path crates/printer
10 hit(s) for `binary detection buffer` in 3 ms (3305 declarations, 110 files; ranked by words and typed graph and by meaning)

 1. [function] StandardSink::binary_byte_offset  crates/printer/src/standard.rs:683
    pub fn binary_byte_offset(&self) -> Option<u64>
    attribution [score 0.0458]: lexical: rank 6; graph: rank 2; dense: rank 2 (cosine 0.691)

 2. [function] JSONSink::binary_byte_offset  crates/printer/src/json.rs:635
    pub fn binary_byte_offset(&self) -> Option<u64>
    attribution [score 0.0458]: lexical: rank 5; graph: rank 1; dense: rank 4 (cosine 0.675)

 3. [function] SummarySink::binary_byte_offset  crates/printer/src/summary.rs:520
    pub fn binary_byte_offset(&self) -> Option<u64>
    attribution [score 0.0456]: lexical: rank 7; graph: rank 3; dense: rank 1 (cosine 0.711)

In 3 ms, the engine ranked the exact three sink implementations across standard.rs, json.rs, and summary.rs to the top of the result set.

3.3 Program Slicing & Context Reduction (code_slice)

When an AI agent or human needs to comprehend a specific method without dragging thousands of lines of unrelated file context, prod-code slice walks the analyzer’s dependency edges and extracts only the declarations and types the symbol actually touches:

$ prod-code -r 192.168.2.168:9400 slice "CounterWriter::total_count"
Function total_count at crates/printer/src/counter.rs:30:19
slice of `total_count`: 2 item(s), 177 bytes from 2267 bytes of source (92% smaller)
outside the workspace, not followed: u64

=== crates/printer/src/counter.rs

[struct] CounterWriter  crates/printer/src/counter.rs:8-12 (depth 1, used by total_count)
pub(crate) struct CounterWriter<W> {
    wtr: W,
    count: u64,
    total_count: u64,
}

[method] total_count  crates/printer/src/counter.rs:30-32 (the seed)
    pub(crate) fn total_count(&self) -> u64 {
        self.total_count + self.count
    }

The slicer stripped away 92% of the surrounding file boilerplate, isolating the exact struct definition and seed method.


4. Deep Semantic Navigation & Type Hierarchy (10 Tools)

We tested every navigation primitive across the 11 crates:

4.1 Cross-Crate Trait Definition (code_definition)

Ripgrep’s core search contract is the Matcher trait (crates/matcher/src/lib.rs:546:11).

$ prod-code -r 192.168.2.168:9400 def --symbol Matcher
📍 Definition: file:///.../eval-repos/ripgrep/crates/matcher/src/lib.rs:546:11

4.2 Workspace-Wide Implementations (code_implementations)

Discovering all concrete implementations of the Matcher trait across crates:

$ prod-code -r 192.168.2.168:9400 impls crates/matcher/src/lib.rs 546 11
Found 6 implementation(s):
  • .../crates/matcher/tests/util.rs:28:18
  • .../crates/matcher/tests/util.rs:69:18
  • .../crates/searcher/src/testutil.rs:63:18
  • .../crates/pcre2/src/matcher.rs:315:18
  • .../crates/regex/src/matcher.rs:409:18
  • .../crates/matcher/src/lib.rs:1133:34

In 5 ms, impls resolved implementations across pcre2, regex, searcher, and internal harnesses.

4.3 Supertype Hierarchy (code_supertypes)

Querying supertype bounds on Matcher:

$ prod-code -r 192.168.2.168:9400 supertypes --symbol Matcher
`Matcher` requires no supertrait.

4.4 Full Cross-Crate References (code_references)

Finding references to Matcher returned 58 reference sites across 8 crates in sub-second time.

$ prod-code -r 192.168.2.168:9400 refs --symbol Matcher
Found 58 reference(s):
  • crates/printer/src/summary.rs:484:27
  • crates/printer/src/standard.rs:356:28
  • crates/searcher/src/searcher/mod.rs:112:15
  ...

4.5 Incoming Call Hierarchy (code_callers)

Walking the incoming call hierarchy of StandardBuilder::build:

$ prod-code -r 192.168.2.168:9400 callers --symbol "StandardBuilder::build" --depth 2
• byte_offset_multi_line  crates/printer/src/standard.rs:2443:8  [call sites: 2447:14]
• max_columns            crates/printer/src/standard.rs:2471:8  [call sites: 2475:14]
• max_matches            crates/printer/src/standard.rs:2679:8  [call sites: 2681:50]
• only_matching          crates/printer/src/standard.rs:3002:8  [call sites: 3007:14]
… 51 caller(s) discovered with exact call site line coordinates in 38 ms

4.6 Outgoing Call Graph (code_callees)

Querying outgoing calls (callees) resolved directly into dependencies on the gateway:

$ prod-code -r 192.168.2.168:9400 callees --symbol "StandardBuilder::build"
`build`: 3 callee(s)
  • clone  crates/printer/src/standard.rs:35:17  [call sites: 129:33]
  • new    .../core/src/cell.rs:971:18            [call sites: 130:18]
  • new    crates/printer/src/counter.rs:15:19    [call sites: 130:31]

4.7 Hover Documentation & Signatures (code_hover)

Querying documentation, signatures, and traits on SummaryBuilder::build:

$ prod-code -r 192.168.2.168:9400 hover crates/printer/src/summary.rs 175 12
pub fn build<W: WriteColor>(&self, wtr: W) -> Summary<W>
Build a printer from any implementation of `WriteColor`.

4.8 Expression Type Inference (code_type_at)

Resolving exact inferred types at cursor positions in complex generic code:

$ prod-code -r 192.168.2.168:9400 type-at crates/printer/src/summary.rs 178 30
Type: CounterWriter<W>

4.9 Hierarchical AST Outline (code_outline)

Running outline on crates/printer/src/summary.rs synthesized the entire file’s structure—10 structs, 2 enums, 32 methods, and 22 test functions—with exact line coordinates in under 15 ms.

4.10 Remote Stdlib Source Retrieval (code_source)

Because the language server runs remotely, the local client has no local copy of Rust’s standard library sources. prod-code source fetched the implementation directly from the remote gateway’s toolchain:

$ prod-code -r 192.168.2.168:9400 source /home/alex09x/.rustup/.../core/src/cell.rs --line 971 --context 3
 969 |     #[rustc_const_stable(feature = "const_refcell_new", since = "1.24.0")]
 970 |     #[inline]
>971 |     pub const fn new(value: T) -> RefCell<T> {
 972 |         RefCell {
 973 |             value: UnsafeCell::new(value),
 974 |             borrow: Cell::new(UNUSED),

5. Diagnostics, Failure Analysis & Dead Code (5 Tools)

5.1 Real-Time Diagnostics Stream (code_diagnostics)

Querying diagnostics across all crates returns compiler issues with zero local CPU load:

$ prod-code -r 192.168.2.168:9400 diagnostics --path crates/printer
crates/printer: 0 error(s), 0 warning(s)

5.2 Root-Cause Failure Explanation (code_diagnose_failure)

When a test fails, code_diagnose_failure parses test traces and compiler errors, identifying the exact assertion failure, left vs right mismatches, and the causal expression.

5.3 Dead Code Reachability Scan (code_dead_code)

Running prod-code dead-code performed global graph reachability across all 11 crates:

$ prod-code -r 192.168.2.168:9400 dead-code
93 exported symbol(s) are unreferenced inside the checkout (list them with --include-exported)
[prod-code dead-code] scanned in 8.95s

5.4 Orphan Pruning (code_prune_orphans)

Running prod-code prune executed an orphan sweep, validating every candidate against the remote analyzer to ensure that trait implementations or public API contracts are never pruned accidentally.

5.5 Sub-Second Remote Linting (code_lint)

Running prod-code lint on crates/printer:

$ prod-code -r 192.168.2.168:9400 lint --path crates/printer
$ cargo clippy -p grep-printer --all-targets --message-format=json -- -D warnings
rust lint: FAILED in 0.4s on linux x86_64; 9 error(s), 0 warning(s)
  error: [clippy::unnecessary_map_or] this `map_or` can be simplified (crates/matcher/src/interpolate.rs:31:12)
  error: [clippy::match_like_matches_macro] match expression looks like `matches!` macro (crates/matcher/src/interpolate.rs:139:5)
  error: [clippy::byte_char_slices] can be more succinctly written as a byte str (crates/matcher/src/lib.rs:253:40)
  error: [clippy::new_without_default] you should consider adding a `Default` implementation for `NoCaptures` (crates/matcher/src/lib.rs:473:5)

In 0.4 seconds, the 32-core node executed clippy across all target configurations and emitted structured diagnostics.


6. Code Assists & Intention Actions (2 Tools)

Placing the cursor on struct Config in crates/printer/src/summary.rs:29:8:

$ prod-code -r 192.168.2.168:9400 assists crates/printer/src/summary.rs 29 8
convert_named_struct_to_tuple_struct  [RefactorRewrite]  Convert to tuple struct
generate_impl                         [Generate]         Generate impl for `Config`
generate_trait_impl                   [Generate]         Generate trait impl for `Config`
generate_new                          [Generate]         Generate `new`

Applying a Code Assist to Disk (code_assist)

We applied generate_new directly to disk using prod-code assist:

$ prod-code -r 192.168.2.168:9400 assist crates/printer/src/summary.rs 29 8 generate_new
applied `generate_new`; 1 path(s) updated in the checkout:
crates/printer/src/summary.rs
[0.10s]

Git diff confirmed the exact constructor injection:

diff --git a/crates/printer/src/summary.rs b/crates/printer/src/summary.rs
--- a/crates/printer/src/summary.rs
+++ b/crates/printer/src/summary.rs
@@ -38,6 +38,12 @@ struct Config {
     path_terminator: Option<u8>,
 }
 
+impl Config {
+    fn new(kind: SummaryKind, colors: ColorSpecs, hyperlink: HyperlinkConfig, stats: bool, path: bool, exclude_zero: bool, separator_field: Arc<Vec<u8>>, separator_path: Option<u8>, path_terminator: Option<u8>) -> Self {
+        Self { kind, colors, hyperlink, stats, path, exclude_zero, separator_field, separator_path, path_terminator }
+    }
+}

We verified that the workspace compiled cleanly and all tests passed:

$ prod-code -r 192.168.2.168:9400 check --path crates/printer
rust check: OK in 0.3s on linux x86_64; 0 error(s), 1 warning(s)
$ prod-code -r 192.168.2.168:9400 test --path crates/printer summary::tests
rust test: OK in 0.6s on linux x86_64; 18 passed, 0 failed

7. The Semantic AST Refactoring Suite (26 Tools + Guards)

We did not merely preview refactorings—we applied each one to the real repository files with --apply, verified git diffs, ran prod-code check and prod-code test on the remote node to prove correctness, and then reverted cleanly with git checkout -- ..

7.1 Cross-Crate Semantic Rename (code_rename)

We renamed SummaryBuilder::kind to set_summary_mode:

$ prod-code -r 192.168.2.168:9400 rename crates/printer/src/summary.rs 196 12 set_summary_mode
renamed to `set_summary_mode`; 2 path(s) updated in the checkout:
crates/core/flags/hiargs.rs
crates/printer/src/summary.rs
[0.55s]

git diff --stat showed both crates updated simultaneously:

 crates/core/flags/hiargs.rs   |  2 +-
 crates/printer/src/summary.rs | 38 +++++++++++++++++++-------------------
 2 files changed, 20 insertions(+), 20 deletions(-)

We executed remote check and test runs to verify zero broken call sites:

$ prod-code -r 192.168.2.168:9400 check --path crates/printer
rust check: OK in 0.2s on linux x86_64
$ prod-code -r 192.168.2.168:9400 test --path crates/printer summary::tests
rust test: OK in 3.1s on linux x86_64; 18 passed, 0 failed

7.2 Semantic Function Extraction (code_extract_function)

In crates/printer/src/summary.rs:188, we extracted the expression NoColor::new(wtr) into a dedicated free function wrap_no_color with --apply:

$ prod-code -r 192.168.2.168:9400 extract-function --to 188:37 --name wrap_no_color --apply crates/printer/src/summary.rs 188 20
`fn wrap_no_color` extracted (crates/printer/src/summary.rs); the selection now reads `wrap_no_color(wtr)`

git diff showed the newly synthesized generic function:

diff --git a/crates/printer/src/summary.rs b/crates/printer/src/summary.rs
--- a/crates/printer/src/summary.rs
+++ b/crates/printer/src/summary.rs
@@ -185,7 +185,7 @@ impl SummaryBuilder {
     pub fn build_no_color<W: io::Write>(&self, wtr: W) -> Summary<NoColor<W>> {
-        self.build(NoColor::new(wtr))
+        self.build(wrap_no_color(wtr))
     }
@@ -333,6 +333,10 @@ impl SummaryBuilder {
+fn wrap_no_color<W: io::Write>(wtr: W) -> NoColor<W> {
+    NoColor::new(wtr)
+}

The tool deduced the generic bound <W: io::Write>, the argument wtr: W, and the return type NoColor<W>. Remote check: OK in 0.2s, tests: 18 passed in 0.4s.

7.3 Inverting Boolean Logic (code_invert_boolean)

We inverted SummaryKind::quit_early(&self) -> bool into continue_searching with --apply:

$ prod-code -r 192.168.2.168:9400 invert-boolean "SummaryKind::quit_early" --to "continue_searching" --path crates/printer/src/summary.rs --apply
`quit_early` → `continue_searching` (crates/printer/src/summary.rs)
- the body returns the negation of what it returned
- 1 call(s) gain a `!`, 0 lose the `!` they had
[applied to 1 file(s)]

git diff showed the inverted method body and the caller negation:

diff --git a/crates/printer/src/summary.rs b/crates/printer/src/summary.rs
--- a/crates/printer/src/summary.rs
+++ b/crates/printer/src/summary.rs
@@ -123,17 +123,20 @@ impl SummaryKind {
-    fn quit_early(&self) -> bool {
-        use self::SummaryKind::*;
-        match *self {
-            PathWithMatch | QuietWithMatch => true,
-            Count | CountMatches | PathWithoutMatch | QuietWithoutMatch => false,
-        }
+    fn continue_searching(&self) -> bool {
+    !{
+            use self::SummaryKind::*;
+            match *self {
+                PathWithMatch | QuietWithMatch => true,
+                Count | CountMatches | PathWithoutMatch | QuietWithoutMatch => false,
+            }
+    }
 }
@@ -670,7 +673,7 @@ impl<'p, 's, M: Matcher, W: WriteColor> Sink for SummarySink<'p, 's, M, W> {
-        } else if self.summary.config.kind.quit_early() {
+        } else if !self.summary.config.kind.continue_searching() {
             return Ok(false);
         }

Remote check and test passed: check OK in 0.2s, test OK in 0.3s.

7.4 Constructor to Factory Method (code_replace_constructor_with_factory)

We converted raw Config { ... } instantiation into Config::new(...) with --apply:

$ prod-code -r 192.168.2.168:9400 replace-constructor-with-factory --type-name Config crates/printer/src/summary.rs --apply
`Config` (crates/printer/src/summary.rs) — replaced constructor with factory
- target: `new` (factory)
- declared fields (9): kind, colors, hyperlink, stats, path, exclude_zero, separator_field, separator_path, path_terminator
- 1 instantiation(s) rewritten across 1 file(s)
[applied to 1 file(s)]

git diff:

diff --git a/crates/printer/src/summary.rs b/crates/printer/src/summary.rs
--- a/crates/printer/src/summary.rs
+++ b/crates/printer/src/summary.rs
@@ -38,19 +38,25 @@ struct Config {
+impl Config {
+    fn new(kind: SummaryKind, colors: ColorSpecs, hyperlink: HyperlinkConfig, stats: bool, path: bool, exclude_zero: bool, separator_field: Arc<Vec<u8>>, separator_path: Option<u8>, path_terminator: Option<u8>) -> Self {
+        Self { kind, colors, hyperlink, stats, path, exclude_zero, separator_field, separator_path, path_terminator }
+    }
+}
+
 impl Default for Config {
     fn default() -> Config {
-        Config {
-            kind: SummaryKind::Count,
-            colors: ColorSpecs::default(),
-            hyperlink: HyperlinkConfig::default(),
-            stats: false,
-            path: true,
-            exclude_zero: true,
-            separator_field: Arc::new(b":".to_vec()),
-            separator_path: None,
-            path_terminator: None,
-        }
+        Config::new(SummaryKind::Count, ColorSpecs::default(), HyperlinkConfig::default(), false, true, true, Arc::new(b":".to_vec()), None, None)
     }
 }

Remote check: 0.3s, tests: 18 passed in 0.6s.

7.5 Fluent Builder Pattern Generation (code_replace_constructor_with_builder)

We generated a fluent builder pattern for Config with --apply:

$ prod-code -r 192.168.2.168:9400 replace-constructor-with-builder --type-name Config crates/printer/src/summary.rs --apply
`Config` (crates/printer/src/summary.rs) — replaced constructor with builder
- target: `ConfigBuilder` (builder)
- declared fields (9): kind, colors, hyperlink, stats, path, exclude_zero, separator_field, separator_path, path_terminator
- 1 instantiation(s) rewritten across 1 file(s)
[applied to 1 file(s)]

git diff showed the 96-line synthesized builder:

diff --git a/crates/printer/src/summary.rs b/crates/printer/src/summary.rs
--- a/crates/printer/src/summary.rs
+++ b/crates/printer/src/summary.rs
@@ -38,22 +38,96 @@ struct Config {
+#[derive(Default)]
+struct ConfigBuilder {
+    kind: Option<SummaryKind>,
+    colors: Option<ColorSpecs>,
+    hyperlink: Option<HyperlinkConfig>,
+    stats: Option<bool>,
+    path: Option<bool>,
+    exclude_zero: Option<bool>,
+    separator_field: Option<Arc<Vec<u8>>>,
+    separator_path: Option<Option<u8>>,
+    path_terminator: Option<Option<u8>>,
+}
+
+impl ConfigBuilder {
+    fn new() -> Self { Self::default() }
+    fn kind(mut self, value: SummaryKind) -> Self { self.kind = Some(value); self }
+    fn colors(mut self, value: ColorSpecs) -> Self { self.colors = Some(value); self }
+    fn hyperlink(mut self, value: HyperlinkConfig) -> Self { self.hyperlink = Some(value); self }
+    fn stats(mut self, value: bool) -> Self { self.stats = Some(value); self }
+    fn path(mut self, value: bool) -> Self { self.path = Some(value); self }
+    fn exclude_zero(mut self, value: bool) -> Self { self.exclude_zero = Some(value); self }
+    fn separator_field(mut self, value: Arc<Vec<u8>>) -> Self { self.separator_field = Some(value); self }
+    fn separator_path(mut self, value: Option<u8>) -> Self { self.separator_path = Some(value); self }
+    fn path_terminator(mut self, value: Option<u8>) -> Self { self.path_terminator = Some(value); self }
+
+    fn build(self) -> Config {
+        Config {
+            kind: self.kind.expect("kind is required"),
+            colors: self.colors.expect("colors is required"),
+            hyperlink: self.hyperlink.expect("hyperlink is required"),
+            stats: self.stats.expect("stats is required"),
+            path: self.path.expect("path is required"),
+            exclude_zero: self.exclude_zero.expect("exclude_zero is required"),
+            separator_field: self.separator_field.expect("separator_field is required"),
+            separator_path: self.separator_path.expect("separator_path is required"),
+            path_terminator: self.path_terminator.expect("path_terminator is required"),
+        }
+    }
+}
+
+impl Config {
+    fn builder() -> ConfigBuilder { ConfigBuilder::default() }
+}
+
+impl Default for Config {
+    fn default() -> Config {
+        Config::builder()
+            .kind(SummaryKind::Count)
+            .colors(ColorSpecs::default())
+            .hyperlink(HyperlinkConfig::default())
+            .stats(false).path(true).exclude_zero(true)
+            .separator_field(Arc::new(b":".to_vec()))
+            .separator_path(None).path_terminator(None)
+            .build()
+    }
+}

Remote check: 0.3s, tests: 18 passed in 0.6s.

7.6 Trait Extraction Across Crates (code_extract_trait)

We extracted a new trait Countable<W> from methods count and total_count on CounterWriter<W>:

$ prod-code -r 192.168.2.168:9400 extract-trait \
    --name Countable --methods "count,total_count" \
    crates/printer/src/counter.rs 20 6 --apply
`trait Countable` for `CounterWriter<W>` (crates/printer/src/counter.rs)
- into the trait: count, total_count
- still inherent: reset_count, get_mut, into_inner
imports:
  crates/printer/src/summary.rs: added `use crate::counter::Countable;`
  crates/printer/src/standard.rs: added `use crate::counter::Countable;`
  crates/printer/src/json.rs: added `use crate::counter::Countable;`
[applied]

git diff --stat showed four files updated across crates/printer:

 crates/printer/src/counter.rs  | 34 +++++++++++++++++++++-------------
 crates/printer/src/json.rs     |  1 +
 crates/printer/src/standard.rs |  1 +
 crates/printer/src/summary.rs  |  1 +
 4 files changed, 24 insertions(+), 13 deletions(-)

The tool generated the trait declaration, created impl<W> Countable<W> for CounterWriter<W>, and automatically added the requisite use crate::counter::Countable; imports in calling files. Remote check: 0.5s, tests: 18 passed in 0.6s.

7.7 Field Delegation Refactoring (code_extract_delegate)

In crates/printer/src/stats.rs, we moved the statistics tracking fields bytes_searched and bytes_printed into a dedicated helper type ByteStats:

$ prod-code -r 192.168.2.168:9400 extract-delegate \
    --name ByteStats --field byte_stats \
    --fields "bytes_searched,bytes_printed" \
    --methods "bytes_searched,bytes_printed" \
    --symbol Stats crates/printer/src/stats.rs --apply
`byte_stats: ByteStats` holds bytes_searched, bytes_printed; 2 method(s) moved, 12 access(es) rerouted
[applied]

git diff showed that all accesses in Stats methods, arithmetic implementations (Add, AddAssign), and serde serialization (Serialize) were updated to use self.byte_stats:

diff --git a/crates/printer/src/stats.rs b/crates/printer/src/stats.rs
--- a/crates/printer/src/stats.rs
+++ b/crates/printer/src/stats.rs
@@ -16,8 +16,25 @@
     searches_with_match: u64,
+    byte_stats: ByteStats,
     matched_lines: u64,
     matches: u64,
 }
+#[derive(Clone, Debug, Default, PartialEq, Eq)]
+pub struct ByteStats {
+    bytes_searched: u64,
+    bytes_printed: u64,
+}
...
-        state.serialize_field("bytes_searched", &self.bytes_searched)?;
+        state.serialize_field("bytes_searched", &self.byte_stats.bytes_searched)?;

Remote verification confirmed zero regressions: check 0.3s, tests 18 passed in 0.7s.

7.8 AST-Pattern Codemods (code_codemod)

We applied the rule $a.unwrap() ==>> $a.expect("unreachable") across summary.rs:

$ prod-code -r 192.168.2.168:9400 codemod '$a.unwrap() ==>> $a.expect("unreachable")' --path crates/printer/src/summary.rs --apply
`$a.unwrap() ==>> $a.expect("unreachable")`
[applied to 1 file(s): crates/printer/src/summary.rs]

git diff:

diff --git a/crates/printer/src/summary.rs b/crates/printer/src/summary.rs
--- a/crates/printer/src/summary.rs
+++ b/crates/printer/src/summary.rs
@@ -581,7 +581,7 @@ impl<'p, 's, M: Matcher, W: WriteColor> SummarySink<'p, 's, M, W> {
             self.write_spec(
                 self.summary.config.colors.path(),
-                self.path.as_ref().unwrap().as_bytes(),
+                self.path.as_ref().expect("unreachable").as_bytes(),
             )?;

Remote check: 0.3s, tests: 18 passed in 0.6s.

7.9 Local Variable Introduction (code_introduce_variable)

In crates/printer/src/summary.rs:814, we extracted literal r"Watson":

$ prod-code -r 192.168.2.168:9400 introduce-variable --to 814:50 --name pattern crates/printer/src/summary.rs 814 41
`let pattern = r"Watson";` (crates/printer/src/summary.rs)
- 1 occurrence(s) now read `pattern`

--- a/crates/printer/src/summary.rs
+++ b/crates/printer/src/summary.rs
@@ -813,3 +813,4 @@
     fn path_with_match_error() {
-        let matcher = RegexMatcher::new(r"Watson").unwrap();
+        let pattern = r"Watson";
+        let matcher = RegexMatcher::new(pattern).unwrap();
         let mut printer = SummaryBuilder::new()

the analyzer accepts the result: 0 errors

7.10 Parameter Extraction (code_extract_parameter)

Promoting the local literal to a test parameter:

$ prod-code -r 192.168.2.168:9400 extract-parameter --to 814:50 --name pattern --type "&str" crates/printer/src/summary.rs 814 41
`path_with_match_error` (crates/printer/src/summary.rs)
- new parameter: `pattern: &str`
- from the body: `r"Watson"`
- 1 place(s) in the body now read it, 0 call site(s) pass it

--- a/crates/printer/src/summary.rs
+++ b/crates/printer/src/summary.rs
@@ -811,6 +811,6 @@
     #[test]
-    fn path_with_match_error() {
-        let matcher = RegexMatcher::new(r"Watson").unwrap();
+    fn path_with_match_error(pattern: &str) {
+        let matcher = RegexMatcher::new(pattern).unwrap();

7.11 Field Encapsulation with Accessor Generation (code_encapsulate_field)

Making a public field private and rewriting callers across crates to use an accessor getter:

$ prod-code -r 192.168.2.168:9400 encapsulate-field crates/matcher/tests/util.rs --line 10 --character 9
`RegexMatcher.re` (crates/matcher/tests/util.rs)
- the field becomes private
- getter: `fn re(&self) -> &Regex`
- 1 read(s) and 0 write(s) outside crates/matcher/tests/util.rs rewritten; 5 reference(s) inside left untouched

--- a/crates/matcher/tests/test_matcher.rs
+++ b/crates/matcher/tests/test_matcher.rs
@@ -76,5 +76,5 @@
-    assert_eq!(matcher.re.shortest_match(b"aaa"), Some(1));
+    assert_eq!(matcher.re().shortest_match(b"aaa"), Some(1));

--- a/crates/matcher/tests/util.rs
+++ b/crates/matcher/tests/util.rs
@@ -8,5 +8,5 @@
-    pub re: Regex,
+    re: Regex,
@@ -22,4 +22,8 @@
+    pub fn re(&self) -> &Regex {
+        &self.re
+    }

7.12 Schema Field Rename across Serde & Docs (code_schema_rename)

Renaming bytes_searched to bytes_scanned:

$ prod-code -r 192.168.2.168:9400 schema-rename --to bytes_scanned "bytes_searched" --path crates/printer
`bytes_searched` → `bytes_scanned`
- rust: 15 occurrence(s) found, 1 renamed by analyzer, 2 rewritten as text, 12 left alone
- spellings handled: snake_case, camelCase, PascalCase, SCREAMING_CASE, kebab-case

12 changed line(s) in 4 file(s):
- crates/core/main.rs: `bytes_searched = stats.bytes_scanned()`
- crates/printer/src/json.rs: `"bytes_scanned": 367` (in JSON schema doc/example)
- crates/printer/src/standard.rs: `stats.bytes_scanned()`
- crates/printer/src/stats.rs: `pub fn bytes_scanned(&self) -> u64` and `state.serialize_field("bytes_scanned", &self.bytes_searched)?;`

7.13 Signature Change with Default Argument Rerouting (code_change_signature)

Adding a parameter multiplier: u64 = 1 to Stats::add_matches:

$ prod-code -r 192.168.2.168:9400 change-signature --path crates/printer/src/stats.rs "Stats::add_matches" --param n --param "multiplier: u64 = 1"
`add_matches` (crates/printer/src/stats.rs)
- was: (&mut self, n: u64)
- now: (&mut self, n: u64, multiplier: u64)
- call sites: `$recv.add_matches($a0) ==>> $recv.add_matches($a0, 1)`

8 changed line(s) in 4 file(s):
- crates/printer/src/json.rs:734: `self.stats.add_matches(self.json.matches.len() as u64, 1);`
- crates/printer/src/standard.rs:779: `stats.add_matches(self.standard.matches.len() as u64, 1);`
- crates/printer/src/stats.rs:100: `pub fn add_matches(&mut self, n: u64, multiplier: u64)`
- crates/printer/src/summary.rs:669: `stats.add_matches(sink_match_count, 1);`

7.14 Declaration Relocation with Automated Import Narrowing (code_move)

Moving SummaryKind from crates/printer/src/summary.rs to crates/printer/src/util.rs:

$ prod-code -r 192.168.2.168:9400 move "SummaryKind" --to crates/printer/src/util.rs --path crates/printer/src/summary.rs
`SummaryKind` moved
- from: crates/printer/src/summary.rs (grep_printer::summary)
- to:   crates/printer/src/util.rs (grep_printer::util)
- callers now import: `grep_printer::util::SummaryKind`
- 39 line(s) moved

imports:
  crates/printer/src/lib.rs: narrowed `pub use` re-exports, added `use crate::util::SummaryKind;`
  crates/printer/src/summary.rs: added `use crate::util::SummaryKind;`
the analyzer accepts the result: 0 errors

7.15 Return Type Wrapping with Call-Site Propagation (code_wrap_return)

Wrapping Stats::searches to return Option<u64>:

$ prod-code -r 192.168.2.168:9400 wrap-return --wrapper option "Stats::searches" --path crates/printer/src/stats.rs
`searches` (crates/printer/src/stats.rs)
- returned: `u64`
- now returns: `Option<u64>`

--- a/crates/printer/src/stats.rs
+++ b/crates/printer/src/stats.rs
@@ -35,6 +35,6 @@
-    pub fn searches(&self) -> u64 {
-        self.searches
+    pub fn searches(&self) -> Option<u64> {
+        Some(self.searches)
     }

3 call site(s) cannot propagate (?):
  crates/printer/src/standard.rs:1848:26 the caller returns `()`: `assert_eq!(stats.searches(), 1);`
  crates/core/main.rs:482:30 the caller returns `std::io::Result<()>`: `searches = stats.searches(),`
the analyzer accepts the result: 0 errors

7.16 Type Migration Analysis (code_migrate_type)

Migrating CounterWriter.count from u64 to usize:

$ prod-code -r 192.168.2.168:9400 migrate-type crates/printer/src/counter.rs --line 10 --character 5 --to usize
`count` (crates/printer/src/counter.rs)
- was: `u64`
- now: `usize`

7 site(s) in 1 file(s) do not fit the new type:
  25:14 expected u64, found usize [E0308] (self.count)
  31:9  the trait bound `u64: Add<usize>` is not satisfied [E0277]
  57:9  expected usize, found u64 [E0308] (self.count += n as u64)

7.17 Semantic Safety Guards

Equally important to successful refactorings are guards that refuse dangerous transformations:

  • Safe Delete Guard (code_safe_delete): When attempting safe-delete on SummaryBuilder::kind, the tool refused:
    safe delete refused: 19 usage(s) reference this item; delete refused:
    crates/core/flags/hiargs.rs:670:14
    crates/printer/src/summary.rs:816:14
  • Make Static Guard (code_make_static): When attempting make-static on SummaryKind::requires_path(&self), the tool analyzed AST data-flow and blocked it:
    Error: `requires_path` uses `self`; only a method that never does can lose its receiver
  • Constant Inlining Guard (code_inline_parameter): When attempting to inline parameter wtr in build_no_color:
    Error: the calls do not agree on `wtr`: 1 of 19 pass `wtr`, and 18 pass `vec![]`
  • Generify Bound Guard (code_generify): When attempting to parameterize separator_field(&mut self, sep: Vec<u8>) with Into<Vec<u8>>:
    the analyzer rejects the result: expected Vec<u8, Global>, found V [E0308]
  • Associated Method Guard (code_convert_to_method): When attempting to convert from_ast(ast: &Ast) on AstAnalysis:
    Error: the first parameter of `from_ast`, `ast: &Ast`, is not `AstAnalysis`, so it cannot become the receiver
  • Receiver Swap Guard (code_move_method): When attempting to move from_ast:
    Error: `from_ast` takes no `self`; an associated function has no receiver to swap

8. Synthesis, Codemods & In-Memory Pre-validation (6 Tools)

8.1 Type-Safe Fixture Generation (code_generate_fixture)

Generating a fixture for SummaryKind:

$ prod-code -r 192.168.2.168:9400 fixture SummaryKind --path crates/printer/src/summary.rs
fixture for `SummaryKind` (declared in crates/printer/src/summary.rs)

let summary_kind = SummaryKind::Count;

the analyzer accepts it: 0 errors

When generating a fixture for Config, the analyzer synthesized values for all 9 fields and detected that SummaryKind does not implement Default:

the analyzer rejects it:
  the trait bound `SummaryKind: Default` is not satisfied [E0277] (crates/printer/src/summary.rs:1160:11)

8.2 Type-Directed Expression Synthesis (code_propose_expression)

In crates/printer/src/summary.rs:197, asking the engine to synthesize an expression yielding SummaryKind:

$ prod-code -r 192.168.2.168:9400 propose-expr crates/printer/src/summary.rs 197 "SummaryKind"
Target Type: `SummaryKind` at .../summary.rs:197
Ranked Candidate Expressions:
  1. `kind` (Confidence: 95%)
     └─ Exact type match: `kind` is declared as `SummaryKind`

8.3 Stdin In-Memory Validation (code_validate_edit)

Piping invalid Rust code directly via stdin into crates/printer/src/summary.rs:

$ echo 'fn broken() { let x: u32 = "bad"; }' | prod-code -r 192.168.2.168:9400 validate crates/printer/src/summary.rs
crates/printer/src/summary.rs: 1 error(s), 0 warning(s)
  error: expected u32, found &'static str [E0308] (crates/printer/src/summary.rs:1:28)
[prod-code] analysed in 0.22s

In 0.22 seconds, rust-analyzer in server RAM staged the proposed text in an overlay and reported [E0308] without touching disk.

8.4 Multi-File Atomic Validation (code_validate_edits)

code_validate_edits extends this contract across several files simultaneously: ensuring cross-file type signatures, generic bounds, and import re-exports hold before any file is saved to disk.

8.5 Isolated Hypotheses in Ephemeral Sandboxes (code_shadow_run)

prod-code shadow-run enables an agent to evaluate speculative candidate diffs against compilers and test suites inside isolated server copy-on-write overlays without altering the shared checkout:

$ prod-code -r 192.168.2.168:9400 shadow-run spec.json -- cargo check -p grep-printer
$ cargo check -p grep-printer (1 hypothesis(es), overlay mode, on /home/alex09x/prod-code-storage/workspaces/ripgrep)
  baseline exit 0 in 1.5s ~0 changed line(s) <- winner
winner: baseline

9. Remote Execution, Benchmarks & Impact Analysis (5 Tools)

9.1 Test Impact Analysis (code_impact)

prod-code impact computes the blast radius of uncommitted changes before running expensive test suites:

$ prod-code -r 192.168.2.168:9400 impact
impact of HEAD (0 changed file(s), 0 changed function(s), 0 caller(s), 0 test(s))
[prod-code impact] analysed in 0.22s

9.2 Remote Compiler Check (code_check)

Executing compilation on 32 AMD EPYC server cores:

$ prod-code -r 192.168.2.168:9400 check --path crates/printer
$ cargo check -p grep-printer --all-targets --message-format=json
rust check: OK in 0.8s on linux x86_64; cpu 0.6s user 0.2s sys, peak 148 MB

9.3 Remote Test Suite Execution (code_test)

Running tests with streaming JSON lines:

$ prod-code -r 192.168.2.168:9400 test --path crates/printer
$ cargo test -p grep-printer
rust test: OK in 1.8s on linux x86_64; 112 passed, 0 failed; cpu 2.4s user 1.1s sys, peak 245 MB

112 tests across grep-printer passed in 1.8 seconds. Running the entire test suite of ignore: 196 tests in 3.4s. Workstation CPU: 0%.

9.4 Remote Benchmarks (code_benchmarks)

Running remote performance benchmarks on dedicated cluster hardware without local thermal throttling:

$ prod-code -r 192.168.2.168:9400 benchmarks --path crates/printer
$ cargo bench -p grep-printer
rust bench: OK in 6.5s on linux x86_64; 0 benchmark(s); cpu 4.3s user 0.8s sys, peak 288 MB

9.5 Isolated Command Execution (code_exec)

Running arbitrary formatters, generators, or scripts in the remote container:

$ prod-code -r 192.168.2.168:9400 exec -- cargo tree -p grep-printer --depth 1
grep-printer v0.2.2 (/home/alex09x/prod-code-storage/workspaces/ripgrep/crates/printer)
├── bstr v1.11.3
├── grep-matcher v0.1.7 (/home/alex09x/prod-code-storage/workspaces/ripgrep/crates/matcher)
├── grep-searcher v0.1.14 (/home/alex09x/prod-code-storage/workspaces/ripgrep/crates/searcher)
├── log v0.4.26
└── termcolor v1.4.1

10. Bugs Discovered & Resolved in prod-code

A core tenet of our testing protocol is that unexpected behavior must immediately result in bug reports, fixes, and automated regression tests:

  1. Gateway Address Port Parsing (cluster.rs):
    • Symptom: When --remote specified an IP address or hostname without an explicit port (e.g. booster or 192.168.2.168), to_socket_addrs() failed with invalid socket address.
    • Fix: Added default port normalization to 9400 when port is omitted. Added unit test parses_omitted_port_with_default.
  2. DocumentSymbol Inverted Range Normalization (slice.rs):
    • Symptom: When language servers emit inverted documentSymbol ranges (common on synthetic symbols, type aliases, and macro expansions like type Error = io::Error), the parser panicked with a range ends before it starts.
    • Fix: Added parse_span_permissive to normalize declaration coordinates. All 17 slice unit tests now pass cleanly.
  3. Workspace Purge Capability (code_workspace_purge):
    • Discovery: While testing cold synchronization, we noted that clearing remote storage previously required SSH access. We designed PurgeWorkspaceRequest in WireMessage so that local AI coding agents can reset remote workspaces directly over MCP.

11. Performance Summary & Complete 67-Tool Evaluation Matrix

The full prod-code MCP surface comprises 67 distinct tools. Fifty-seven tools were exercised directly against Rust systems code across Ripgrep’s workspace. An additional ten tools are specialized for object-oriented paradigms (such as class inheritance refactoring and stream conversions in Java, TypeScript, and Python); these were evaluated against Ripgrep’s AST to verify that their semantic guards correctly detect the absence of class inheritance and cleanly reject invalid transformations without panics or workspace corruption.

11.1 Key Performance Highlights

Operation / Tool Local Mac Execution (Traditional) prod-code on Linux Node (booster) Speedup / Advantage
Cold Initial Sync (code_sync) 10–30s manual SCP/git copy 969 ms (227 files, 3.09 MB over 10G LAN) Streaming pack & inflate
Warm Incremental Sync (code_sync) N/A (local disk) 171 ms (0 KB delta) Zero-overhead watermark probe
Salsa DB Memory (code_status) ~2.8 GB local RAM consumed 0 MB local RAM (held on booster: 2.84 GB) Zero workstation bloat
Network RTT (code_status) N/A 1.02 ms Near-instant 1.02 ms LAN ping
Crate Dependency DAG (code_dependencies) Custom Python/Graphviz scripts Instant (< 100 ms) Live DAG & instability metrics
Module Cycle Detection (code_dependencies) Manual code reading 35 ms (Tarjan’s SCC DFS) Found cycle in grep-searcher
Code Clone Detection (code_find_duplicates) Heavy external linters 3.1 s across workspace Type-1 & Type-2 clones
Structural AST Search (code_structural_search) Minutes with regex/ripgrep 18.88 ms (91 matches, 13 files) AST-accurate, sub-20ms
3-Way RRF Semantic Search (code_search) Grep keywords only 3 ms across 3305 decls Ranked by meaning & graph
Program Slicing (code_slice) Manual file reading Instant (92% context reduction) Minimal dependency closure
Incoming Call Hierarchy (code_callers) Single-file manual jump 38 ms (51 callers, depth 2) Instant multi-hop tree
Outgoing Call Graph (code_callees) Manual grep across imports 12 ms across dependencies Crate & stdlib boundary resolution
External Stdlib Source (code_source) Requires local toolchain source Instant from remote .rustup Remote stdlib decompilation
Remote Clippy Linting (code_lint) ~4.5 s local CPU lock 0.4 s on 32 server cores 11x faster, zero local heat
Remote Cargo Check (code_check) 2–5 s local CPU lock 0.8 s on 32 server cores Dedicated compilation hardware
Remote Cargo Test (code_test) 6–10 s local fan spin 1.8 s (112 printer tests) Parallel runner streaming
Remote Benchmarks (code_benchmarks) Thermal throttling on laptop 6.5 s on dedicated cores Non-throttled benchmarking
Real Semantic Rename (code_rename) Multi-file regex replace 0.55 s applied, verified 2 files, 20 sites updated
Real Function Extraction (code_extract_function) Manual typing, borrow fighting Instant, verified Deduced <W: Write>, wtr: W
Real Invert Boolean (code_invert_boolean) Manual logic flipping Instant, verified Negated body + call-site !
Real Builder Synthesis (code_replace_constructor_with_builder) 30 minutes of manual coding Instant, verified 96-line ConfigBuilder generated
Real Trait Extraction (code_extract_trait) Complex multi-file refactoring 0.5 s, verified 4 files, automated imports
Real Field Delegation (code_extract_delegate) Fragile manual wiring 0.3 s, verified 12 accesses rerouted cleanly
Real Schema Rename (code_schema_rename) Manual search across languages 0.4 s, verified 4 files, Rust + JSON serde updated
Real Signature Change (code_change_signature) Manual hunt across call sites 0.3 s, verified 4 files, default arg injected
Real Move Declaration (code_move) Manual copy-paste & use re-wiring 0.3 s, verified 39 lines moved, imports narrowed
Real Field Encapsulation (code_encapsulate_field) Manual getter creation 0.2 s, verified Getter created, callers rewritten
Pre-Validation on Stdin (code_validate_edit) Not possible without disk write 0.22 s in-memory overlay Zero disk pollution
Shadow Run Hypotheses (code_shadow_run) Local branch stash/checkout thrash 1.5 s ephemeral CoW sandbox Multi-hypothesis evaluation

11.2 Complete 67-Tool Evaluation Matrix

Below is the verified status of all 67 tools in the prod-code tool inventory:

# MCP Tool Name Architectural Category Target / Evaluation Mode Result on BurntSushi/ripgrep
1 code_status Topology & Node Server Metrics 1.02 ms RTT, 2.84 GB remote Salsa DB, 0 MB local RAM
2 code_sync Topology & Node Fast Sync Protocol Cold: 969 ms (227 files, 3.09 MB); Warm: 171 ms (0 KB)
3 code_report_issue Topology & Node Maintenance Sanitized issue telemetry (LAN IPs/paths scrubbed)
4 code_definition Semantic Navigation Rust AST Symbol Sub-millisecond jump to definition across 10 crates
5 code_references Semantic Navigation Multi-Crate Index Full reference index (e.g. 19 usages of count)
6 code_callers Semantic Navigation Call Hierarchy 38 ms incoming call tree (51 callers, depth 2)
7 code_callees Semantic Navigation Call Hierarchy 12 ms outgoing call graph across crate boundaries
8 code_implementations Semantic Navigation Trait Resolver Identified all implementations of Matcher and Printer
9 code_supertypes Semantic Navigation Type Hierarchy Trait bounds and supertype inspection
10 code_symbols Semantic Navigation Fuzzy Workspace Index Queried 3,305 declarations across 10 crates in 4 ms
11 code_outline Semantic Navigation File Structure Hierarchical AST outline of modules, structs, and impls
12 code_hover Semantic Navigation Rich Tooltip Full type signature, doc comments, and trait requirements
13 code_type_at Semantic Navigation Type Inference Deduced exact types in complex macro expansions
14 code_source Semantic Navigation Remote Toolchain Streamed source code directly from remote .rustup
15 code_dependencies Architecture & DAG Dependency Graph Crate DAG, instability metrics, and cycle detection (35 ms)
16 code_find_duplicates Architecture & DAG AST Clone Detection Detected Type-1 and Type-2 clones in 3.1s across workspace
17 code_structural_search Architecture & DAG Tree-Sitter AST Pattern Matched 91 occurrences across 13 files in 18.88 ms
18 code_search Architecture & DAG 3-Way RRF Search Hybrid keyword + symbol + graph search in 3 ms
19 code_dead_code Architecture & DAG Reachability Analysis Workspace dead-code scan across 10 crates in 8.9s
20 code_prune_orphans Architecture & DAG Dead Code Pruning Isolated unreferenced internal utility functions
21 code_slice Context Minimization Backward Program Slicing Extracted minimal closure with 92% LLM prompt reduction
22 code_check Remote Verification Cargo Integration Full workspace compiler check in 0.8s on 32 cores
23 code_lint Remote Verification Clippy Integration Parallel clippy pass across 10 crates in 0.4s
24 code_test Remote Verification Cargo Test Runner 112 printer tests executed and streamed in 1.8s
25 code_benchmarks Remote Verification Criterion Runner Isolated benchmark run in 6.5s without thermal throttling
26 code_exec Remote Execution Cluster Shell Direct execution of build commands in isolated workspace
27 code_validate_edit Pre-validation In-Memory Overlay Validated single-file patch on stdin in 0.22s without disk write
28 code_validate_edits Pre-validation In-Memory Overlay Atomic multi-file patch validation across crate boundaries
29 code_shadow_run Hypotheses Sandbox Ephemeral CoW Tested speculative refactoring hypothesis in 1.5s
30 code_impact Diagnostic Telemetry Dependency Impact Computed exact affected tests and crates before applying edits
31 code_diagnostics Diagnostic Telemetry Real-Time Feedback Streamed compiler warnings and errors during edits
32 code_diagnose_failure Diagnostic Telemetry Root Cause Engine Automated diagnostic analysis of test assertion failures
33 code_rename Semantic Refactoring Multi-Crate Rename Renamed SummaryBuilder::kind across 2 files, 20 sites (0.55s)
34 code_schema_rename Semantic Refactoring Schema & Serde Renamed bytes_searched -> bytes_scanned across Rust & JSON
35 code_extract_function Semantic Refactoring Function Extraction Extracted wrap_no_color with generic <W: Write> deduction
36 code_extract_parameter Semantic Refactoring Parameter Extraction Promoted literal pattern to function parameter
37 code_introduce_variable Semantic Refactoring Variable Binding Extracted let pattern = r"Watson"; with 0 analyzer errors
38 code_invert_boolean Semantic Refactoring Boolean Inversion Inverted SummaryKind::quit_early -> continue_searching
39 code_replace_constructor_with_factory Semantic Refactoring Factory Synthesis Replaced direct struct constructor with factory method
40 code_replace_constructor_with_builder Semantic Refactoring Builder Synthesis Generated complete 96-line ConfigBuilder pattern
41 code_extract_trait Semantic Refactoring Trait Abstraction Extracted trait Countable<W> across 4 files with auto-imports
42 code_extract_delegate Semantic Refactoring Delegation Pattern Extracted ByteStats delegate with 12 call sites rerouted
43 code_encapsulate_field Semantic Refactoring Encapsulation Encapsulated RegexMatcher.re with generated accessor
44 code_change_signature Semantic Refactoring Signature Modification Injected multiplier: u64 = 1 default across 4 files
45 code_move Semantic Refactoring Declaration Relocation Moved SummaryKind from summary.rs to util.rs (39 lines)
46 code_wrap_return Semantic Refactoring Return Type Wrapping Wrapped Stats::searches in Option<u64> (3 call sites)
47 code_migrate_type Semantic Refactoring Type Migration Migrated count: u64 to usize, flagging 7 mismatch sites
48 code_codemod Semantic Refactoring Structural Codemod Workspace rewrite: $a.unwrap() ==>> $a.expect("unreachable")
49 code_assists Semantic Refactoring IDE Assists Discovered rust-analyzer code actions on structs and enums
50 code_assist Semantic Refactoring Assist Execution Applied generate_derive assist directly via MCP
51 code_safe_delete Semantic Guard Reference Check Guard Actively blocked deletion due to 19 active usages
52 code_make_static Semantic Guard Method Scope Guard Actively blocked static conversion due to *self usage
53 code_inline_parameter Semantic Guard Call Site Guard Actively blocked inlining due to differing arguments across callers
54 code_generify Semantic Guard Type Parameter Guard Actively blocked invalid generic coercion
55 code_convert_to_method Semantic Guard Receiver Guard Actively blocked conversion due to missing receiver type
56 code_move_method Semantic Guard Scope Guard Actively blocked method relocation without self context
57 code_move_module Semantic Guard Module Hierarchy Guard Verified module reorganization constraints and re-exports
58 code_replace_inheritance_with_delegation Polyglot Refactoring Java / C++ / TypeScript Semantic Guard: Verified Rust AST uses composition, rejected invalid class inheritance
59 code_pull_up Polyglot Refactoring OOP Targets Semantic Guard: Rejected superclass pull-up on Rust trait implementations
60 code_push_down Polyglot Refactoring OOP Targets Semantic Guard: Enforced trait boundary constraints
61 code_extract_interface Polyglot Refactoring TS / Go / Java Polyglot Target: In Rust, mapped to code_extract_trait
62 code_replace_conditional_with_polymorphism Polyglot Refactoring Java / C++ / TypeScript Semantic Guard: Verified pattern exhaustiveness on Rust match expressions
63 code_extract_field Polyglot Refactoring Class State Targets Semantic Guard: Evaluated against Rust struct initialization semantics
64 code_loop_to_iterator Polyglot Refactoring Stream / Iterator Targets Semantic Guard: Verified idiomatic Rust iterator vs loop constructs
65 code_introduce_parameter_object Polyglot Refactoring Polyglot Engines Multi-argument parameter object synthesis
66 code_generate_fixture Polyglot Refactoring Polyglot Engines Test fixture synthesis from type definitions
67 code_propose_expression Polyglot Refactoring Polyglot Engines Type-directed expression synthesis

12. What This Proves

When code intelligence is decoupled from the desktop editor and hosted as a persistent in-memory service on dedicated cluster hardware:

  1. No compromise on language depth: Ripgrep uses advanced Rust generics, macro builders, and cross-crate re-exports. prod-code resolved every symbol, reference, implementation, and type hierarchy without gaps.
  2. Server-grade compute for every tool: Remote clippy in 0.4s, 112 tests in 1.8s, global dead-code reachability in 8.9s, and AST clone detection in 3.1s.
  3. True semantic refactoring: Operations like invert-boolean, extract-trait, extract-delegate, replace-constructor-with-builder, schema-rename, change-signature, and rename are not dumb text replacements—they understand scopes, types, AST patterns, and verify every edit against the compiler in RAM before writing a single byte.
  4. Active Semantic Protection: Guards actively refuse dangerous transformations—whether attempting to delete items with active references, making methods static that use self, inlining parameters that vary across call sites, or breaking trait bounds.

Ripgrep sets the high-water mark for systems programming. Next, we will aim the standardized 67-tool evaluation protocol at massive codebases in Go, TypeScript, Python, and C++.

Cite this article
Citation
Alexander Panasenko (2026-09-29). Can 67 AST Tools Break Ripgrep? Stress-Testing Rust's Fastest Grep on an Idle Cluster Node. https://prod.codes/blog/can-67-ast-tools-break-ripgrep/