diff --git a/.claude/hooks/rtk-rewrite.sh b/.claude/hooks/rtk-rewrite.sh index b67beee..a62f23b 100755 --- a/.claude/hooks/rtk-rewrite.sh +++ b/.claude/hooks/rtk-rewrite.sh @@ -2,6 +2,7 @@ # RTK auto-rewrite hook for Claude Code PreToolUse:Bash # Transparently rewrites raw commands to their rtk equivalents. # Outputs JSON with updatedInput to modify the command before execution. +# Source of truth: hooks/rtk-rewrite.sh (keep .claude/hooks copy in sync) # Guards: skip silently if dependencies missing if ! command -v rtk &>/dev/null || ! command -v jq &>/dev/null; then @@ -84,16 +85,24 @@ elif echo "$MATCH_CMD" | grep -qE '^cargo[[:space:]]+check([[:space:]]|$)'; then REWRITTEN="${ENV_PREFIX}$(echo "$CMD_BODY" | sed 's/^cargo check/rtk cargo check/')" elif echo "$MATCH_CMD" | grep -qE '^cargo[[:space:]]+install([[:space:]]|$)'; then REWRITTEN="${ENV_PREFIX}$(echo "$CMD_BODY" | sed 's/^cargo install/rtk cargo install/')" -elif echo "$MATCH_CMD" | grep -qE '^cargo[[:space:]]+nextest([[:space:]]|$)'; then - REWRITTEN="${ENV_PREFIX}$(echo "$CMD_BODY" | sed 's/^cargo nextest/rtk cargo nextest/')" elif echo "$MATCH_CMD" | grep -qE '^cargo[[:space:]]+fmt([[:space:]]|$)'; then REWRITTEN="${ENV_PREFIX}$(echo "$CMD_BODY" | sed 's/^cargo fmt/rtk cargo fmt/')" # --- File operations --- +# Search priority (mandatory): rgai > rg > grep +# Tier 1: semantic intent search (grepai/rgai) -> rtk rgai +# Tier 2: exact search via ripgrep -> rtk grep (rtk grep runs rg -> grep fallback internally) +# Tier 3: exact search via grep -> rtk grep +elif echo "$MATCH_CMD" | grep -qE '^(grepai|rgai)[[:space:]]+search([[:space:]]|$)'; then + REWRITTEN="${ENV_PREFIX}$(echo "$CMD_BODY" | sed -E 's/^(grepai|rgai)[[:space:]]+search[[:space:]]+/rtk rgai /')" +elif echo "$MATCH_CMD" | grep -qE '^rgai[[:space:]]+'; then + REWRITTEN="${ENV_PREFIX}$(echo "$CMD_BODY" | sed -E 's/^rgai[[:space:]]+/rtk rgai /')" elif echo "$MATCH_CMD" | grep -qE '^cat[[:space:]]+'; then REWRITTEN="${ENV_PREFIX}$(echo "$CMD_BODY" | sed 's/^cat /rtk read /')" -elif echo "$MATCH_CMD" | grep -qE '^(rg|grep)[[:space:]]+'; then - REWRITTEN="${ENV_PREFIX}$(echo "$CMD_BODY" | sed -E 's/^(rg|grep) /rtk grep /')" +elif echo "$MATCH_CMD" | grep -qE '^rg[[:space:]]+'; then + REWRITTEN="${ENV_PREFIX}$(echo "$CMD_BODY" | sed -E 's/^rg /rtk grep /')" +elif echo "$MATCH_CMD" | grep -qE '^grep[[:space:]]+'; then + REWRITTEN="${ENV_PREFIX}$(echo "$CMD_BODY" | sed -E 's/^grep /rtk grep /')" elif echo "$MATCH_CMD" | grep -qE '^ls([[:space:]]|$)'; then REWRITTEN="${ENV_PREFIX}$(echo "$CMD_BODY" | sed 's/^ls/rtk ls/')" elif echo "$MATCH_CMD" | grep -qE '^tree([[:space:]]|$)'; then diff --git a/.gitignore b/.gitignore index e68eca8..d9a3311 100644 --- a/.gitignore +++ b/.gitignore @@ -35,4 +35,10 @@ benchmark-report.md *.sqlite *.sqlite3 rtk_tracking.db -claudedocs \ No newline at end of file +claudedocs + +# grepai local index (project-specific, not portable) +.grepai/ + +# Claude Code local settings (user-specific) +.claude/settings.local.json \ No newline at end of file diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 4d0cba1..2e9ff64 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -176,7 +176,7 @@ Database: ~/.local/share/rtk/history.db ## Module Organization -### Complete Module Map (30 Modules) +### Complete Module Map (49 Modules) ``` ┌────────────────────────────────────────────────────────────────────────┐ @@ -191,11 +191,14 @@ GIT git.rs status, diff, log 85-99% ✓ branch, checkout CODE SEARCH grep_cmd.rs grep 60-80% ✓ + rgai_cmd.rs rgai (semantic) 85% ✓ + grepai.rs (grepai delegation) N/A ✓ diff_cmd.rs diff 70-85% ✓ find_cmd.rs find 50-70% ✓ FILE OPS ls.rs ls 50-70% ✓ read.rs read 40-90% ✓ + tree.rs (internal for ls) N/A ✓ EXECUTION runner.rs err, test 60-99% ✓ summary.rs smart (heuristic) 50-80% ✓ @@ -204,32 +207,43 @@ EXECUTION runner.rs err, test 60-99% ✓ LOGS/DATA log_cmd.rs log 70-90% ✓ json_cmd.rs json 80-95% ✓ +BUILD cargo_cmd.rs cargo build/test 80-90% ✓ + JS/TS STACK lint_cmd.rs lint 84% ✓ tsc_cmd.rs tsc 83% ✓ next_cmd.rs next 87% ✓ prettier_cmd.rs prettier 70% ✓ + format_cmd.rs format (black/ruff) 70% ✓ playwright_cmd.rs playwright 94% ✓ prisma_cmd.rs prisma 88% ✓ vitest_cmd.rs vitest 99.5% ✓ pnpm_cmd.rs pnpm 70-90% ✓ - -CONTAINERS container.rs podman, docker 60-80% ✓ - -VCS gh_cmd.rs gh 26-87% ✓ + npm_cmd.rs npm run, npx 70-80% ✓ PYTHON ruff_cmd.rs ruff check/format 80%+ ✓ pytest_cmd.rs pytest 90%+ ✓ - pip_cmd.rs pip list/outdated 70-85% ✓ + pip_cmd.rs pip/uv 70-85% ✓ -GO go_cmd.rs go test/build/vet 75-90% ✓ +GO go_cmd.rs go test/build/vet 80-90% ✓ golangci_cmd.rs golangci-lint 85% ✓ -NETWORK wget_cmd.rs wget 85-95% ✓ +CONTAINERS container.rs podman, docker 60-80% ✓ + +VCS gh_cmd.rs gh 26-87% ✓ + +NETWORK curl_cmd.rs curl 70% ✓ + wget_cmd.rs wget 85-95% ✓ DEPENDENCIES deps.rs deps 80-90% ✓ ENVIRONMENT env_cmd.rs env 60-80% ✓ +ANALYTICS cc_economics.rs cc-economics N/A ✓ + ccusage.rs (internal) N/A ✓ + display_helpers.rs (internal) N/A ✓ + discover/ discover N/A ✓ + learn/ (error learning) N/A ✓ + SYSTEM init.rs init N/A ✓ gain.rs gain N/A ✓ config.rs (internal) N/A ✓ @@ -237,18 +251,21 @@ SYSTEM init.rs init N/A ✓ SHARED utils.rs Helpers N/A ✓ filter.rs Language filters N/A ✓ tracking.rs Token tracking N/A ✓ + parser/ Output parser fwk N/A ✓ + rgai_arg_tests (test-only) N/A ✓ ``` -**Total: 46 modules** (29 command modules + 17 infrastructure modules) +**Total: 49 modules** (33 command modules + 16 infrastructure/internal modules) ### Module Count Breakdown -- **Command Modules**: 29 (directly exposed to users) -- **Infrastructure Modules**: 17 (utils, filter, tracking, config, init, gain, etc.) +- **Command Modules**: 33 (directly exposed to users) +- **Infrastructure Modules**: 16 (utils, filter, tracking, config, init, gain, parser, display, etc.) - **Git Commands**: 7 operations (status, diff, log, add, commit, push, branch/checkout) -- **JS/TS Tooling**: 8 modules (modern frontend/fullstack development) -- **Python Tooling**: 3 modules (ruff, pytest, pip) -- **Go Tooling**: 2 modules (go test/build/vet, golangci-lint) +- **JS/TS Tooling**: 10 modules (modern frontend/fullstack development) +- **Python Tooling**: 3 modules (ruff, pytest, pip/uv) +- **Go Tooling**: 2 modules (go, golangci-lint) +- **Semantic Search**: 2 modules (rgai_cmd + grepai delegation) --- diff --git a/INSTALL.md b/INSTALL.md index 55b32fd..6cbf2d7 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -69,6 +69,15 @@ rtk gain # MUST show token savings, not "command not found" ## Project Initialization +### Search Priority + +**Search priority: rgai > rg > grep.** + +- Use `rtk rgai` first for semantic/intention-based discovery. +- Use `rtk grep` for exact/regex matching. +- `rtk grep` internally follows `rg -> grep` backend fallback. +- For fully raw output, use `rtk proxy `. + ### Recommended: Global Hook-First Setup **Best for: All projects, automatic RTK usage** @@ -229,7 +238,8 @@ cp ~/.claude/settings.json.bak ~/.claude/settings.json ```bash rtk ls . # Compact tree view rtk read file.rs # Optimized reading -rtk grep "pattern" . # Grouped search results +rtk rgai "query" # Semantic code search +rtk grep "pattern" . # Exact/regex search (internal rg -> grep fallback) ``` ### Git @@ -332,6 +342,7 @@ Before each session: - [ ] Verify RTK is installed: `rtk --version` - [ ] If not installed → follow "Install from fork" - [ ] If project not initialized → `rtk init` +- [ ] Search: use `rtk rgai` first, then `rtk grep` for exact/regex - [ ] Use `rtk` for ALL git/pnpm/test/vitest commands - [ ] Check savings: `rtk gain` diff --git a/README.md b/README.md index 19a2250..df7be48 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,15 @@ With rtk: **~45,000 tokens** → **70% reduction** > Estimates based on medium-sized TypeScript/Rust projects. Actual savings vary by project size. +## Search Priority + +**Search priority: rgai > rg > grep.** + +- Use `rtk rgai` first for semantic/intention-based discovery. +- Use `rtk grep` for exact/regex matching. +- `rtk grep` internally follows `rg -> grep` backend fallback. +- For fully raw output, use `rtk proxy `. + ## Installation ### ⚠️ Pre-Installation Check (REQUIRED) @@ -133,7 +142,8 @@ rtk read file.rs # Smart file reading rtk read file.rs -l aggressive # Signatures only (strips bodies) rtk smart file.rs # 2-line heuristic code summary rtk find "*.rs" . # Compact find results -rtk grep "pattern" . # Grouped search results +rtk rgai "auth token refresh" # Semantic code search +rtk grep "pattern" . # Exact/regex search (internal rg -> grep fallback) ``` ### Git @@ -425,6 +435,11 @@ The most effective way to use rtk is with the **auto-rewrite hook** for Claude C **Result**: 100% rtk adoption across all conversations and subagents, zero token overhead in Claude's context. +**Search ladder**: +- `rtk rgai` for semantic discovery +- `rtk grep` for exact/regex follow-up (`rg -> grep` fallback) +- `rtk proxy ...` when you need fully raw behavior + ### What Are Hooks? **For Beginners**: @@ -516,12 +531,16 @@ The hook is included in this repository at `.claude/hooks/rtk-rewrite.sh`. To us ### Commands Rewritten +Search rewrite order is strict and deterministic: `rgai > rg > grep`. + | Raw Command | Rewritten To | |-------------|-------------| | `git status/diff/log/add/commit/push/pull/branch/fetch/stash` | `rtk git ...` | | `gh pr/issue/run` | `rtk gh ...` | | `cargo test/build/clippy` | `rtk cargo ...` | | `cat ` | `rtk read ` | +| `grepai/rgai search ` | `rtk rgai ` | +| `rgai ` | `rtk rgai ` | | `rg/grep ` | `rtk grep ` | | `ls` | `rtk ls` | | `vitest/pnpm test` | `rtk vitest run` | diff --git a/benchmarks/RESULTS.md b/benchmarks/RESULTS.md new file mode 100644 index 0000000..9bae898 --- /dev/null +++ b/benchmarks/RESULTS.md @@ -0,0 +1,271 @@ +# Code Search Benchmark: grep vs rtk grep vs rtk rgai vs head_n + +## Environment & Reproduction + +``` +Date: Sat Feb 14 22:34:25 UTC 2026 +Commit: 4b0a413562c775757d5bc09a6ff966b4e532508c +rtk_bin: /Users/andrew/Programming/rtk/target/release/rtk +rtk: rtk 0.15.3 +grep: grep (BSD grep, GNU compatible) 2.6.0-FreeBSD +tiktoken_encoding: cl100k_base +rtk_grep_max: 200 +rgai_max: 8 +head_n_lines: 100 +OS: Darwin MacBook-Pro-Andy.local 25.2.0 Darwin Kernel Version 25.2.0: Tue Nov 18 21:09:56 PST 2025; root:xnu-12377.61.12~1/RELEASE_ARM64_T6041 arm64 +CPU: Apple M4 Pro +Rust files: 54 +Total LOC: 23240 +``` + +## Dataset: rtk-ai/rtk @ `4b0a413562c775757d5bc09a6ff966b4e532508c` + +**Reproduction**: +```bash +rtk --version +bash benchmarks/bench_code.sh +python3 benchmarks/analyze_code.py +python3 -m unittest discover -s benchmarks/tests -p 'test_*.py' +``` + +## Methodology + +### Metrics (reported separately, NO composite score) + +| Metric | Definition | Purpose | +|--------|-----------|---------| +| Output bytes | `wc -c` of stdout | Raw size footprint | +| Output tokens | `tiktoken` (`cl100k_base`) on full stdout | Model-aligned token cost | +| Token Efficiency (TE) | `output_tokens / grep_output_tokens` | Token compression vs baseline | +| Result count | Effective output lines / no-result aware count | Distinguish compactness vs empty results | +| Gold hit rate | `% gold_files found` (plus found/min files) | Relevance/correctness | +| Timing | Median of 5 runs, plus min/max in summaries | Performance distribution | + +**Critical rule**: if `expect_results=true` and `result_count==0`, mark as **MISS**. +For regex category, `rtk rgai` is marked `EXPECTED_UNSUPPORTED` by design. + +### Categories + +| Category | Queries | +|----------|---------| +| A: Exact Identifier | 6 | +| B: Regex Pattern | 6 | +| C: Semantic Intent | 10 | +| D: Cross-File Pattern Discovery | 5 | +| E: Edge Cases | 3 | + +## Category A: Exact Identifier Search + +| ID | Query | Tool | Bytes | Tokens | TE | Result Count | Gold Hit | Timing (med) | Status | +|----|-------|------|-------|--------|----|-------------|----------|-------------|--------| +| A1 | TimedExecution | grep | 10338 | 2927 | 1.000 | 104 | 100% (34/30) | 6.0ms | OK | +| A1 | TimedExecution | rtk_grep | 6527 | 1979 | 0.676 | 159 | 100% (34/30) | 25.0ms | OK | +| A1 | TimedExecution | rtk_rgai | 2797 | 841 | 0.287 | 94 | 60% (8/30) | 11.0ms | LOW_COVERAGE | +| A1 | TimedExecution | head_n | 9933 | 2810 | 0.960 | 100 | 100% (32/30) | 0μs | OK | +| A2 | FilterLevel | grep | 2196 | 605 | 1.000 | 23 | 100% (3/3) | 5.0ms | OK | +| A2 | FilterLevel | rtk_grep | 902 | 288 | 0.476 | 25 | 100% (3/3) | 25.0ms | OK | +| A2 | FilterLevel | rtk_rgai | 691 | 223 | 0.369 | 32 | 100% (3/3) | 10.0ms | OK | +| A2 | FilterLevel | head_n | 2196 | 605 | 1.000 | 23 | 100% (3/3) | 0μs | OK | +| A3 | classify_command | grep | 2524 | 626 | 1.000 | 22 | 100% (2/2) | 7.0ms | OK | +| A3 | classify_command | rtk_grep | 817 | 225 | 0.359 | 20 | 100% (2/2) | 24.0ms | OK | +| A3 | classify_command | rtk_rgai | 782 | 200 | 0.319 | 25 | 100% (2/2) | 11.0ms | OK | +| A3 | classify_command | head_n | 2524 | 626 | 1.000 | 22 | 100% (2/2) | 0μs | OK | +| A4 | package_manager_exec | grep | 918 | 260 | 1.000 | 9 | 100% (5/5) | 7.0ms | OK | +| A4 | package_manager_exec | rtk_grep | 797 | 246 | 0.946 | 21 | 100% (5/5) | 25.0ms | OK | +| A4 | package_manager_exec | rtk_rgai | 1370 | 381 | 1.465 | 44 | 100% (5/5) | 11.0ms | OK | +| A4 | package_manager_exec | head_n | 918 | 260 | 1.000 | 9 | 100% (5/5) | 0μs | OK | +| A5 | strip_ansi | grep | 1852 | 539 | 1.000 | 20 | 100% (5/5) | 8.0ms | OK | +| A5 | strip_ansi | rtk_grep | 1197 | 388 | 0.720 | 33 | 100% (5/5) | 24.0ms | OK | +| A5 | strip_ansi | rtk_rgai | 1264 | 425 | 0.788 | 51 | 100% (5/5) | 10.0ms | OK | +| A5 | strip_ansi | head_n | 1852 | 539 | 1.000 | 20 | 100% (5/5) | 0μs | OK | +| A6 | HISTORY_DAYS | grep | 201 | 61 | 1.000 | 2 | 100% (1/1) | 5.0ms | OK | +| A6 | HISTORY_DAYS | rtk_grep | 182 | 66 | 1.082 | 6 | 100% (1/1) | 24.0ms | OK | +| A6 | HISTORY_DAYS | rtk_rgai | 686 | 208 | 3.410 | 23 | 100% (2/1) | 11.0ms | OK | +| A6 | HISTORY_DAYS | head_n | 201 | 61 | 1.000 | 2 | 100% (1/1) | 0μs | OK | + +### Category A: Exact Identifier Search — Summary + +- **grep**: | TE min/med/max=1.000/1.000/1.000 | gold hit min/med/max=100%/100%/100% | time min/med/max=5.0ms / 6.5ms / 8.0ms +- **rtk_grep**: | TE min/med/max=0.359/0.698/1.082 | gold hit min/med/max=100%/100%/100% | time min/med/max=22.0ms / 24.5ms / 44.0ms +- **rtk_rgai**: | TE min/med/max=0.287/0.579/3.410 | gold hit min/med/max=60%/100%/100% | time min/med/max=10.0ms / 11.0ms / 13.0ms | LOW_COVERAGE=1 +- **head_n**: | TE min/med/max=0.960/1.000/1.000 | gold hit min/med/max=100%/100%/100% | time min/med/max=0μs / 0μs / 0μs + +## Category B: Regex Pattern Search + +> `rtk rgai` does not support regex; misses are EXPECTED_UNSUPPORTED. + +| ID | Query | Tool | Bytes | Tokens | TE | Result Count | Gold Hit | Timing (med) | Status | +|----|-------|------|-------|--------|----|-------------|----------|-------------|--------| +| B1 | fn run\(.*verbose: u8 | grep | 3128 | 999 | 1.000 | 27 | 100% (27/25) | 7.0ms | OK | +| B1 | fn run\(.*verbose: u8 | rtk_grep | 3518 | 1206 | 1.207 | 83 | 100% (27/25) | 25.0ms | OK | +| B1 | fn run\(.*verbose: u8 | rtk_rgai | 3264 | 1065 | 1.066 | 99 | 38% (8/25) | 12.0ms | EXPECTED_UNSUPPORTED | +| B1 | fn run\(.*verbose: u8 | head_n | 3128 | 999 | 1.000 | 27 | 100% (27/25) | 0μs | OK | +| B2 | timer\.track\( | grep | 10764 | 3338 | 1.000 | 116 | 100% (34/30) | 8.0ms | OK | +| B2 | timer\.track\( | rtk_grep | 5723 | 1979 | 0.593 | 158 | 100% (34/30) | 24.0ms | OK | +| B2 | timer\.track\( | rtk_rgai | 2542 | 803 | 0.241 | 93 | 50% (8/30) | 12.0ms | EXPECTED_UNSUPPORTED | +| B2 | timer\.track\( | head_n | 9143 | 2822 | 0.845 | 100 | 100% (32/30) | 0μs | OK | +| B3 | \.unwrap_or\(1\) | grep | 5347 | 1513 | 1.000 | 48 | 100% (20/15) | 7.0ms | OK | +| B3 | \.unwrap_or\(1\) | rtk_grep | 3806 | 1200 | 0.793 | 87 | 100% (20/15) | 24.0ms | OK | +| B3 | \.unwrap_or\(1\) | rtk_rgai | 2777 | 885 | 0.585 | 106 | 50% (8/15) | 11.0ms | EXPECTED_UNSUPPORTED | +| B3 | \.unwrap_or\(1\) | head_n | 5347 | 1513 | 1.000 | 48 | 100% (20/15) | 0μs | OK | +| B4 | #\[cfg\(test\)\] | grep | 2605 | 845 | 1.000 | 41 | 100% (41/35) | 5.0ms | OK | +| B4 | #\[cfg\(test\)\] | rtk_grep | 3098 | 1142 | 1.351 | 125 | 100% (41/35) | 25.0ms | OK | +| B4 | #\[cfg\(test\)\] | rtk_rgai | 2247 | 716 | 0.847 | 101 | 40% (7/35) | 11.0ms | EXPECTED_UNSUPPORTED | +| B4 | #\[cfg\(test\)\] | head_n | 2605 | 845 | 1.000 | 41 | 100% (41/35) | 0μs | OK | +| B5 | HashMap For multi-concept queries, grep exact-substring misses are expected and shown as MISS. + +| ID | Query | Tool | Bytes | Tokens | TE | Result Count | Gold Hit | Timing (med) | Status | +|----|-------|------|-------|--------|----|-------------|----------|-------------|--------| +| C1 | token savings tracking database | grep | 0 | 0 | MISS | 0 | N/A (0/1) | 8.0ms | **MISS** | +| C1 | token savings tracking database | rtk_grep | 45 | 12 | MISS | 0 | 0% (0/1) | 24.0ms | **MISS** | +| C1 | token savings tracking database | rtk_rgai | 2801 | 832 | N/A | 102 | 100% (8/1) | 15.0ms | OK | +| C1 | token savings tracking database | head_n | 0 | 0 | MISS | 0 | N/A (0/1) | 0μs | **MISS** | +| C2 | exit code preservation | grep | 0 | 0 | MISS | 0 | N/A (0/2) | 9.0ms | **MISS** | +| C2 | exit code preservation | rtk_grep | 36 | 11 | MISS | 0 | 0% (0/2) | 25.0ms | **MISS** | +| C2 | exit code preservation | rtk_rgai | 2158 | 702 | N/A | 96 | 80% (8/2) | 12.0ms | OK | +| C2 | exit code preservation | head_n | 0 | 0 | MISS | 0 | N/A (0/2) | 0μs | **MISS** | +| C3 | language aware code filtering | grep | 0 | 0 | MISS | 0 | N/A (0/1) | 8.0ms | **MISS** | +| C3 | language aware code filtering | rtk_grep | 43 | 12 | MISS | 0 | 0% (0/1) | 24.0ms | **MISS** | +| C3 | language aware code filtering | rtk_rgai | 3112 | 926 | N/A | 103 | 100% (8/1) | 14.0ms | OK | +| C3 | language aware code filtering | head_n | 0 | 0 | MISS | 0 | N/A (0/1) | 0μs | **MISS** | +| C4 | output grouping by file | grep | 0 | 0 | MISS | 0 | N/A (0/2) | 8.0ms | **MISS** | +| C4 | output grouping by file | rtk_grep | 37 | 12 | MISS | 0 | 0% (0/2) | 25.0ms | **MISS** | +| C4 | output grouping by file | rtk_rgai | 3348 | 989 | N/A | 105 | 0% (8/2) | 13.0ms | LOW_COVERAGE | +| C4 | output grouping by file | head_n | 0 | 0 | MISS | 0 | N/A (0/2) | 0μs | **MISS** | +| C5 | three tier parser degradation | grep | 0 | 0 | MISS | 0 | N/A (0/1) | 9.0ms | **MISS** | +| C5 | three tier parser degradation | rtk_grep | 43 | 12 | MISS | 0 | 0% (0/1) | 25.0ms | **MISS** | +| C5 | three tier parser degradation | rtk_rgai | 2453 | 741 | N/A | 95 | 50% (7/1) | 13.0ms | OK | +| C5 | three tier parser degradation | head_n | 0 | 0 | MISS | 0 | N/A (0/1) | 0μs | **MISS** | +| C6 | ANSI color stripping cleanup | grep | 0 | 0 | MISS | 0 | N/A (0/1) | 6.0ms | **MISS** | +| C6 | ANSI color stripping cleanup | rtk_grep | 42 | 13 | MISS | 0 | 0% (0/1) | 27.0ms | **MISS** | +| C6 | ANSI color stripping cleanup | rtk_rgai | 2139 | 697 | N/A | 92 | 100% (8/1) | 14.0ms | OK | +| C6 | ANSI color stripping cleanup | head_n | 0 | 0 | MISS | 0 | N/A (0/1) | 0μs | **MISS** | +| C7 | hook installation settings json | grep | 0 | 0 | MISS | 0 | N/A (0/1) | 8.0ms | **MISS** | +| C7 | hook installation settings json | rtk_grep | 45 | 12 | MISS | 0 | 0% (0/1) | 27.0ms | **MISS** | +| C7 | hook installation settings json | rtk_rgai | 2940 | 907 | N/A | 104 | 100% (8/1) | 15.0ms | OK | +| C7 | hook installation settings json | head_n | 0 | 0 | MISS | 0 | N/A (0/1) | 0μs | **MISS** | +| C8 | command classification discover | grep | 0 | 0 | MISS | 0 | N/A (0/1) | 9.0ms | **MISS** | +| C8 | command classification discover | rtk_grep | 45 | 11 | MISS | 0 | 0% (0/1) | 26.0ms | **MISS** | +| C8 | command classification discover | rtk_rgai | 2867 | 796 | N/A | 104 | 100% (8/1) | 13.0ms | OK | +| C8 | command classification discover | head_n | 0 | 0 | MISS | 0 | N/A (0/1) | 0μs | **MISS** | +| C9 | pnpm yarn npm auto detection | grep | 0 | 0 | MISS | 0 | N/A (0/1) | 8.0ms | **MISS** | +| C9 | pnpm yarn npm auto detection | rtk_grep | 42 | 14 | MISS | 0 | 0% (0/1) | 27.0ms | **MISS** | +| C9 | pnpm yarn npm auto detection | rtk_rgai | 2682 | 931 | N/A | 104 | 100% (8/1) | 14.0ms | OK | +| C9 | pnpm yarn npm auto detection | head_n | 0 | 0 | MISS | 0 | N/A (0/1) | 0μs | **MISS** | +| C10 | SQLite retention cleanup policy | grep | 0 | 0 | MISS | 0 | N/A (0/1) | 11.0ms | **MISS** | +| C10 | SQLite retention cleanup policy | rtk_grep | 45 | 12 | MISS | 0 | 0% (0/1) | 25.0ms | **MISS** | +| C10 | SQLite retention cleanup policy | rtk_rgai | 806 | 241 | N/A | 27 | 100% (2/1) | 14.0ms | OK | +| C10 | SQLite retention cleanup policy | head_n | 0 | 0 | MISS | 0 | N/A (0/1) | 0μs | **MISS** | + +### Category C: Semantic Intent Search — Summary + +- **grep**: | time min/med/max=6.0ms / 8.0ms / 37.0ms | MISS=10 +- **rtk_grep**: | gold hit min/med/max=0%/0%/0% | time min/med/max=23.0ms / 25.0ms / 63.0ms | MISS=10 +- **rtk_rgai**: | gold hit min/med/max=0%/100%/100% | time min/med/max=12.0ms / 14.0ms / 18.0ms | LOW_COVERAGE=1 +- **head_n**: | time min/med/max=0μs / 0μs / 0μs | MISS=10 + +## Category D: Cross-File Pattern Discovery + +| ID | Query | Tool | Bytes | Tokens | TE | Result Count | Gold Hit | Timing (med) | Status | +|----|-------|------|-------|--------|----|-------------|----------|-------------|--------| +| D1 | verbose > 0 | grep | 6540 | 2112 | 1.000 | 90 | 100% (36/30) | 6.0ms | OK | +| D1 | verbose > 0 | rtk_grep | 4307 | 1634 | 0.774 | 162 | 100% (36/30) | 25.0ms | OK | +| D1 | verbose > 0 | rtk_rgai | 2238 | 709 | 0.336 | 97 | 50% (8/30) | 11.0ms | LOW_COVERAGE | +| D1 | verbose > 0 | head_n | 6540 | 2112 | 1.000 | 90 | 100% (36/30) | 0μs | OK | +| D2 | anyhow::Result | grep | 753 | 235 | 1.000 | 11 | 100% (11/11) | 8.0ms | OK | +| D2 | anyhow::Result | rtk_grep | 954 | 333 | 1.417 | 35 | 100% (11/11) | 24.0ms | OK | +| D2 | anyhow::Result | rtk_rgai | 2416 | 765 | 3.255 | 102 | 73% (8/11) | 12.0ms | LOW_COVERAGE | +| D2 | anyhow::Result | head_n | 753 | 235 | 1.000 | 11 | 100% (11/11) | 0μs | OK | +| D3 | process::exit | grep | 5234 | 1474 | 1.000 | 47 | 100% (19/15) | 7.0ms | OK | +| D3 | process::exit | rtk_grep | 3682 | 1154 | 0.783 | 84 | 100% (19/15) | 24.0ms | OK | +| D3 | process::exit | rtk_rgai | 2538 | 804 | 0.545 | 106 | 83% (8/15) | 12.0ms | LOW_COVERAGE | +| D3 | process::exit | head_n | 5234 | 1474 | 1.000 | 47 | 100% (19/15) | 0μs | OK | +| D4 | Command::new | grep | 9867 | 2999 | 1.000 | 111 | 100% (24/20) | 5.0ms | OK | +| D4 | Command::new | rtk_grep | 5321 | 1790 | 0.597 | 145 | 100% (24/20) | 25.0ms | OK | +| D4 | Command::new | rtk_rgai | 2283 | 769 | 0.256 | 102 | 57% (8/20) | 12.0ms | LOW_COVERAGE | +| D4 | Command::new | head_n | 8937 | 2700 | 0.900 | 100 | 100% (23/20) | 0μs | OK | +| D5 | from_utf8_lossy | grep | 17304 | 5038 | 1.000 | 157 | 100% (28/25) | 7.0ms | OK | +| D5 | from_utf8_lossy | rtk_grep | 8386 | 2572 | 0.511 | 168 | 100% (28/25) | 25.0ms | OK | +| D5 | from_utf8_lossy | rtk_rgai | 2767 | 867 | 0.172 | 94 | 29% (8/25) | 11.0ms | LOW_COVERAGE | +| D5 | from_utf8_lossy | head_n | 10775 | 3127 | 0.621 | 100 | 43% (17/25) | 0μs | LOW_COVERAGE | + +### Category D: Cross-File Pattern Discovery — Summary + +- **grep**: | TE min/med/max=1.000/1.000/1.000 | gold hit min/med/max=100%/100%/100% | time min/med/max=5.0ms / 7.0ms / 8.0ms +- **rtk_grep**: | TE min/med/max=0.511/0.774/1.417 | gold hit min/med/max=100%/100%/100% | time min/med/max=23.0ms / 25.0ms / 27.0ms +- **rtk_rgai**: | TE min/med/max=0.172/0.336/3.255 | gold hit min/med/max=29%/57%/83% | time min/med/max=11.0ms / 12.0ms / 13.0ms | LOW_COVERAGE=5 +- **head_n**: | TE min/med/max=0.621/1.000/1.000 | gold hit min/med/max=43%/100%/100% | time min/med/max=0μs / 0μs / 0μs | LOW_COVERAGE=1 + +## Category E: Edge Cases + +> Edge cases are discussed per-case; no category-level winner is inferred. + +| ID | Query | Tool | Bytes | Tokens | TE | Result Count | Gold Hit | Timing (med) | Status | +|----|-------|------|-------|--------|----|-------------|----------|-------------|--------| +| E1 | the | grep | 19971 | 5421 | 1.000 | 178 | N/A | 8.0ms | OK | +| E1 | the | rtk_grep | 11273 | 3399 | 0.627 | 239 | N/A | 26.0ms | OK | +| E1 | the | rtk_rgai | 2359 | 779 | 0.144 | 106 | N/A | 10.0ms | OK | +| E1 | the | head_n | 11771 | 3170 | 0.585 | 100 | N/A | 0μs | OK | +| E2 | fn | grep | 77939 | 23141 | 1.000 | 784 | N/A | 7.0ms | OK | +| E2 | fn | rtk_grep | 12744 | 4052 | 0.175 | 264 | N/A | 26.0ms | OK | +| E2 | fn | rtk_rgai | 2733 | 872 | 0.038 | 101 | N/A | 10.0ms | OK | +| E2 | fn | head_n | 10320 | 3103 | 0.134 | 100 | N/A | 0μs | OK | +| E3 | error handling retry backoff | grep | 0 | 0 | N/A | 0 | N/A | 9.0ms | OK | +| E3 | error handling retry backoff | rtk_grep | 42 | 13 | N/A | 0 | N/A | 25.0ms | OK | +| E3 | error handling retry backoff | rtk_rgai | 2340 | 756 | N/A | 102 | N/A | 13.0ms | **UNEXPECTED_HIT** | +| E3 | error handling retry backoff | head_n | 0 | 0 | N/A | 0 | N/A | 0μs | OK | + +## Summary: When to Use Which Tool + +| Situation | Recommended | Evidence | +|-----------|-------------|----------| +| Exact identifier search (Category A) | rtk_grep | median gold hit=100%, MISS=0, LOW_COVERAGE=0, median TE=0.698 | +| Cross-file pattern discovery (Category D) | rtk_grep | median gold hit=100%, MISS=0, LOW_COVERAGE=0, median TE=0.774 | +| Semantic intent search (Category C) | rtk_rgai | median gold hit=100%, MISS=0, LOW_COVERAGE=1, UNEXPECTED_HIT=0, median TE=N/A | +| Regex patterns (Category B) | grep / rtk grep | `rtk rgai` expected unsupported for regex | +| Exact zero-result validation (E3) | grep / rtk grep | Unexpected hits observed for: rtk_rgai | + +## Failure Modes + +### grep +- Floods output on broad/common queries. +- Misses semantic intent queries that do not appear as exact substrings. +- No built-in grouping/truncation. + +### rtk grep +- Output truncation (`--max 200`) can reduce recall in high-frequency queries. +- Still exact-match based (no semantic expansion). + +### rtk rgai +- Regex queries are unsupported by design. +- Can return semantically related content even when strict zero results are expected. +- Quality depends on ranking/model behavior and may vary by environment. + +### head_n (negative control) +- Naive truncation may look token-efficient but is relevance-blind. +- Useful as a floor comparator, not as a production recommendation. + +## Limitations + +- Single codebase benchmark (`src/` Rust files only). +- Gold standards are author-defined and include subjective intent mapping. +- Gold hit is computed from first-run samples; non-deterministic tools may vary across runs. +- Timing is hardware and background-load dependent. diff --git a/benchmarks/analyze_code.py b/benchmarks/analyze_code.py new file mode 100644 index 0000000..2404df3 --- /dev/null +++ b/benchmarks/analyze_code.py @@ -0,0 +1,679 @@ +#!/usr/bin/env python3 +""" +Analyze code-search benchmark results and generate RESULTS.md. + +Rules: + - No composite score. + - Per-category analysis only. + - Report distributions (min/median/max). + - If gold expects results and result_count == 0 => MISS. + - Regex category: rgai is EXPECTED_UNSUPPORTED (not failure). +""" + +from __future__ import annotations + +import csv +import json +import re +import sys +from collections import defaultdict +from pathlib import Path + +SCRIPT_DIR = Path(__file__).resolve().parent +CSV_PATH = SCRIPT_DIR / "results_raw.csv" +ENV_PATH = SCRIPT_DIR / "results_env.txt" +GOLD_PATH = SCRIPT_DIR / "gold_standards.json" +GOLD_AUTO_PATH = SCRIPT_DIR / "gold_auto.json" # ADDED: auto-generated gold +QUALITY_DIR = SCRIPT_DIR / "quality_samples" +RESULTS_PATH = SCRIPT_DIR / "RESULTS.md" + +TOOLS = ("grep", "rtk_grep", "rtk_rgai", "head_n") # CHANGED: added head_n +RECOMMENDABLE_TOOLS = ("grep", "rtk_grep", "rtk_rgai") +CATEGORY_ORDER = [ + "exact_identifier", + "regex_pattern", + "semantic_intent", + "cross_file", + "edge_case", +] +CATEGORY_TITLES = { + "exact_identifier": "Category A: Exact Identifier Search", + "regex_pattern": "Category B: Regex Pattern Search", + "semantic_intent": "Category C: Semantic Intent Search", + "cross_file": "Category D: Cross-File Pattern Discovery", + "edge_case": "Category E: Edge Cases", +} + + +def median_val(values: list[int | float]) -> float: + vals = sorted(values) + if not vals: + return 0.0 + n = len(vals) + if n % 2 == 1: + return float(vals[n // 2]) + return (vals[n // 2 - 1] + vals[n // 2]) / 2.0 + + +def min_val(values: list[int | float]) -> float: + return float(min(values)) if values else 0.0 + + +def max_val(values: list[int | float]) -> float: + return float(max(values)) if values else 0.0 + + +def is_valid_exit(exit_code: int) -> bool: + # 0 = matches/success, 1 = no matches, >=2 = execution error + return exit_code in (0, 1) + + +def normalize_rs_path(path: str) -> str: + p = path.strip(" \t\r\n:;,.()[]{}<>\"'") + p = p.replace("\\", "/") + if "/.../" in p: + p = p.split("/.../", 1)[1] + if "/src/" in p: + p = p.split("/src/", 1)[1] + elif p.startswith("src/"): + p = p[4:] + + p = p.lstrip("./") + p = re.sub(r"/{2,}", "/", p) + return p + + +def extract_filenames(text: str) -> set[str]: + filenames: set[str] = set() + for raw_line in text.splitlines(): + line = raw_line.strip() + if not line: + continue + + # RTK grouped output: + # 📄 /path/to/file.rs (12): + # 📄 parser/mod.rs [9.4] + m = re.match(r"^📄\s+(.+?\.rs)\s*(?:\(|\[|$)", line) + if m: + candidate = normalize_rs_path(m.group(1)) + if candidate.endswith(".rs"): + filenames.add(candidate) + continue + + # grep -rn style: + # /abs/src/file.rs:42:... + # src/file.rs:42:... + m = re.match(r"^(.+?\.rs):\d+(?::|$)", line) + if m: + candidate = normalize_rs_path(m.group(1)) + if candidate.endswith(".rs"): + filenames.add(candidate) + + return filenames + + +def file_matches_gold(gold_file: str, found_files: set[str]) -> bool: + if gold_file in found_files: + return True + + if "/" not in gold_file: + suffix = f"/{gold_file}" + return any(f == gold_file or f.endswith(suffix) for f in found_files) + + return False + + +def compute_gold_hits(sample_text: str, gold_files: list[str]) -> int: + if not gold_files: + return 0 + found_files = extract_filenames(sample_text) + return sum(1 for gf in gold_files if file_matches_gold(gf, found_files)) + + +def infer_no_result_from_sample(sample_text: str, tool: str) -> bool: + text = sample_text.strip() + if not text: + return False + if tool in {"rtk_grep", "rtk_rgai"}: + # rtk no-results marker examples: + # "🔍 0 for 'query'" / "🧠 0 for 'query'" + if re.search(r"(?:🔍|🧠)\s*0\s+for\b", text): + return True + # Fallback in case glyphs differ. + if re.search(r"^\s*0\s+for\b", text): + return True + return False + + +def compute_gold_hit_rate(sample_text: str, gold_files: list[str]) -> float | None: + if not gold_files: + return None + hits = compute_gold_hits(sample_text, gold_files) + return hits / len(gold_files) + + +def compute_gold_found_count(sample_text: str) -> int: + return len(extract_filenames(sample_text)) + + +def is_miss(result_count: int, expect_results: bool) -> bool: + return result_count == 0 and expect_results + + +def format_te(te: float | None, miss: bool) -> str: + if miss: + return "MISS" + if te is None: + return "N/A" + return f"{te:.3f}" + + +def format_pct(te: float | None, miss: bool) -> str: + if miss: + return "MISS" + if te is None: + return "N/A" + savings = (1 - te) * 100 + return f"{savings:.1f}%" + + +def format_gold(rate: float | None, found_count: int, min_required: int) -> str: + if rate is None: + if min_required > 0: + return f"N/A ({found_count}/{min_required})" + return "N/A" + if min_required > 0: + return f"{rate * 100:.0f}% ({found_count}/{min_required})" + return f"{rate * 100:.0f}%" + + +def format_timing(us: float) -> str: + if us >= 1_000_000: + return f"{us / 1_000_000:.2f}s" + if us >= 1_000: + return f"{us / 1_000:.1f}ms" + return f"{us:.0f}μs" + + +def format_timing_range(min_us: float, med_us: float, max_us: float) -> str: + return f"{format_timing(min_us)} / {format_timing(med_us)} / {format_timing(max_us)}" + + +def load_gold_standards() -> tuple[dict, dict]: + with open(GOLD_PATH, encoding="utf-8") as f: + data = json.load(f) + return data["queries"], data.get("metadata", {}) + + +def load_gold_auto() -> dict: # ADDED: load auto-generated gold + """Load auto-generated gold standards from grep output.""" + if not GOLD_AUTO_PATH.exists(): + return {} + with open(GOLD_AUTO_PATH, encoding="utf-8") as f: + data = json.load(f) + return data.get("queries", {}) + + +def load_csv() -> list[dict]: + rows = [] + with open(CSV_PATH, newline="", encoding="utf-8") as f: + reader = csv.DictReader(f) + for row in reader: + if "output_tokens" not in row or row["output_tokens"] in (None, ""): + raise ValueError( + "results_raw.csv is missing 'output_tokens'. " + "Re-run benchmarks/bench_code.sh after installing tiktoken." + ) + row["time_us"] = int(row["time_us"]) + row["output_bytes"] = int(row["output_bytes"]) + row["output_tokens"] = int(row["output_tokens"]) + row["result_count"] = int(row["result_count"]) + row["exit_code"] = int(row["exit_code"]) + row["run"] = int(row["run"]) + rows.append(row) + return rows + + +def load_quality_sample(test_id: str, tool: str) -> str: + path = QUALITY_DIR / f"{test_id}_{tool}.txt" + if path.exists(): + return path.read_text(errors="replace") + return "" + + +def parse_commit_from_env(env_text: str) -> str | None: + m = re.search(r"^Commit:\s*([0-9a-f]{7,40})\s*$", env_text, flags=re.MULTILINE) + return m.group(1) if m else None + + +def compute_metrics(rows: list[dict], gold: dict, gold_auto: dict | None = None) -> list[dict]: # CHANGED: added gold_auto + grouped: dict[tuple[str, str], list[dict]] = defaultdict(list) + for row in rows: + grouped[(row["test_id"], row["tool"])].append(row) + + aggregates: dict[tuple[str, str], dict] = {} + for (tid, tool), runs in grouped.items(): + times = [r["time_us"] for r in runs] + bytess = [r["output_bytes"] for r in runs] + tokens = [r["output_tokens"] for r in runs] # ADDED: token counts + counts = [r["result_count"] for r in runs] + exits = [r["exit_code"] for r in runs] + aggregates[(tid, tool)] = { + "test_id": tid, + "tool": tool, + "category": runs[0]["category"], + "query": runs[0]["query"].strip('"'), + "median_time_us": median_val(times), + "min_time_us": min_val(times), + "max_time_us": max_val(times), + "median_bytes": median_val(bytess), + "median_tokens": median_val(tokens), # ADDED + "median_count": median_val(counts), + "valid": all(is_valid_exit(e) for e in exits), + } + + test_ids = sorted( + set(tid for tid, _ in aggregates.keys()), + key=lambda x: (x[0], int(x[1:]) if x[1:].isdigit() else 0), + ) + + results = [] + for tid in test_ids: + gold_entry = gold.get(tid, {}) + category = gold_entry.get("category", "unknown") + expect = gold_entry.get("expect_results", True) + gold_files = gold_entry.get("gold_files", []) + gold_min_files = int(gold_entry.get("gold_min_files", 0) or 0) + + grep_agg = aggregates.get((tid, "grep")) + grep_tokens = grep_agg["median_tokens"] if grep_agg else 0 + + entry = { + "test_id": tid, + "category": category, + "query": gold_entry.get("query", ""), + "expect_results": expect, + } + + for tool in TOOLS: + agg = aggregates.get((tid, tool)) + if not agg: + continue + + sample = load_quality_sample(tid, tool) + no_result_marker = infer_no_result_from_sample(sample, tool) + adjusted_count = 0 if no_result_marker else int(agg["median_count"]) + + unsupported = category == "regex_pattern" and tool == "rtk_rgai" + miss = is_miss(adjusted_count, expect) and not unsupported + unexpected_hit = (not expect) and adjusted_count > 0 + + ghr = compute_gold_hit_rate(sample, gold_files) if sample else None + found_count = compute_gold_found_count(sample) if sample else 0 + gold_hits = compute_gold_hits(sample, gold_files) if sample else 0 + gold_min_ok = None + if gold_min_files > 0: + gold_min_ok = found_count >= gold_min_files + low_coverage = False + if not miss and not unsupported: + if gold_min_files > 0 and gold_min_ok is False: + low_coverage = True + if ghr is not None and ghr == 0.0: + low_coverage = True + + te = None + if agg["valid"] and grep_tokens > 0: + te = agg["median_tokens"] / grep_tokens + + entry[f"{tool}_bytes"] = agg["median_bytes"] + entry[f"{tool}_tokens"] = agg["median_tokens"] + entry[f"{tool}_count"] = adjusted_count + entry[f"{tool}_time_us"] = agg["median_time_us"] + entry[f"{tool}_min_time_us"] = agg["min_time_us"] + entry[f"{tool}_max_time_us"] = agg["max_time_us"] + entry[f"{tool}_te"] = te + entry[f"{tool}_gold_hit"] = ghr + entry[f"{tool}_gold_found"] = found_count + entry[f"{tool}_gold_hits"] = gold_hits + entry[f"{tool}_gold_min_required"] = gold_min_files + entry[f"{tool}_gold_min_ok"] = gold_min_ok + entry[f"{tool}_low_coverage"] = low_coverage + entry[f"{tool}_valid"] = agg["valid"] + entry[f"{tool}_miss"] = miss + entry[f"{tool}_unsupported"] = unsupported + entry[f"{tool}_unexpected_hit"] = unexpected_hit + + results.append(entry) + + return results + + +def category_tool_stats(cat_metrics: list[dict], tool: str) -> dict: + entries = [m for m in cat_metrics if f"{tool}_bytes" in m and not m.get(f"{tool}_unsupported", False)] + + te_vals = [m[f"{tool}_te"] for m in entries if m.get(f"{tool}_te") is not None and not m.get(f"{tool}_miss", False)] + gold_vals = [m[f"{tool}_gold_hit"] for m in entries if m.get(f"{tool}_gold_hit") is not None] + time_vals = [m[f"{tool}_time_us"] for m in entries] + min_time_vals = [m[f"{tool}_min_time_us"] for m in entries] + max_time_vals = [m[f"{tool}_max_time_us"] for m in entries] + + miss_count = sum(1 for m in entries if m.get(f"{tool}_miss", False)) + unexpected_count = sum(1 for m in entries if m.get(f"{tool}_unexpected_hit", False)) + low_cov_count = sum( + 1 + for m in entries + if m.get(f"{tool}_low_coverage", False) + and not m.get(f"{tool}_miss", False) + ) + + return { + "entries": entries, + "te_vals": te_vals, + "gold_vals": gold_vals, + "time_vals": time_vals, + "min_time_vals": min_time_vals, + "max_time_vals": max_time_vals, + "miss_count": miss_count, + "unexpected_count": unexpected_count, + "low_cov_count": low_cov_count, + "unsupported_count": sum(1 for m in cat_metrics if m.get(f"{tool}_unsupported", False)), + } + + +def pick_best_for_exact(cat_metrics: list[dict]) -> tuple[str, str]: + candidates = [] + for tool in RECOMMENDABLE_TOOLS: + st = category_tool_stats(cat_metrics, tool) + if not st["entries"]: + continue + med_te = median_val(st["te_vals"]) if st["te_vals"] else 1e18 + med_gold = median_val(st["gold_vals"]) if st["gold_vals"] else -1.0 + med_time = median_val(st["time_vals"]) if st["time_vals"] else 1e18 + candidates.append( + (tool, st["miss_count"], st["low_cov_count"], med_gold, med_te, med_time) + ) + + if not candidates: + return "N/A", "Insufficient valid metrics" + + # For exact/cross-file tasks: correctness first, compression second. + candidates.sort(key=lambda x: (x[1], x[2], -x[3], x[4], x[5])) + tool, miss, low_cov, med_gold, med_te, _ = candidates[0] + gold_str = "N/A" if med_gold < 0 else f"{med_gold * 100:.0f}%" + te_str = "N/A" if med_te == 1e18 else f"{med_te:.3f}" + return tool, f"median gold hit={gold_str}, MISS={miss}, LOW_COVERAGE={low_cov}, median TE={te_str}" + + +def pick_best_for_semantic(cat_metrics: list[dict]) -> tuple[str, str]: + candidates = [] + for tool in RECOMMENDABLE_TOOLS: + st = category_tool_stats(cat_metrics, tool) + if not st["entries"]: + continue + med_gold = median_val(st["gold_vals"]) if st["gold_vals"] else -1.0 + med_te = median_val(st["te_vals"]) if st["te_vals"] else 1e18 + miss = st["miss_count"] + low_cov = st["low_cov_count"] + unexpected = st["unexpected_count"] + candidates.append((tool, miss, low_cov, unexpected, -med_gold, med_te, med_gold)) + + if not candidates: + return "N/A", "Insufficient valid metrics" + + # For semantic tasks: misses/coverage first, then relevance, then compression. + candidates.sort(key=lambda x: (x[1], x[2], x[3], x[4], x[5])) + tool, miss, low_cov, unexpected, _, med_te, med_gold = candidates[0] + gold_str = "N/A" if med_gold < 0 else f"{med_gold * 100:.0f}%" + te_str = "N/A" if med_te == 1e18 else f"{med_te:.3f}" + return tool, f"median gold hit={gold_str}, MISS={miss}, LOW_COVERAGE={low_cov}, UNEXPECTED_HIT={unexpected}, median TE={te_str}" + + +def generate_report( + metrics: list[dict], + env_text: str, + gold_queries: dict, + pinned_commit: str, + env_commit: str | None, +) -> str: + lines: list[str] = [] + w = lines.append + + w("# Code Search Benchmark: grep vs rtk grep vs rtk rgai vs head_n\n") # CHANGED: added head_n + w("## Environment & Reproduction\n") + w("```") + w(env_text.strip()) + w("```\n") + + w(f"## Dataset: rtk-ai/rtk @ `{pinned_commit}`\n") + if env_commit and env_commit != pinned_commit: + w( + f"> **WARNING**: benchmark env commit `{env_commit}` differs from pinned " + f"gold commit `{pinned_commit}`. Results are not strictly reproducible.\n" + ) + + w("**Reproduction**:") + w("```bash") + w("rtk --version") + w("bash benchmarks/bench_code.sh") + w("python3 benchmarks/analyze_code.py") + w("python3 -m unittest discover -s benchmarks/tests -p 'test_*.py'") + w("```\n") + + w("## Methodology\n") + w("### Metrics (reported separately, NO composite score)\n") + w("| Metric | Definition | Purpose |") + w("|--------|-----------|---------|") + w("| Output bytes | `wc -c` of stdout | Raw size footprint |") + w("| Output tokens | `tiktoken` (`cl100k_base`) on full stdout | Model-aligned token cost |") + w("| Token Efficiency (TE) | `output_tokens / grep_output_tokens` | Token compression vs baseline |") + w("| Result count | Effective output lines / no-result aware count | Distinguish compactness vs empty results |") + w("| Gold hit rate | `% gold_files found` (plus found/min files) | Relevance/correctness |") + w("| Timing | Median of 5 runs, plus min/max in summaries | Performance distribution |") + w("") + w("**Critical rule**: if `expect_results=true` and `result_count==0`, mark as **MISS**.") + w("For regex category, `rtk rgai` is marked `EXPECTED_UNSUPPORTED` by design.\n") + + w("### Categories\n") + w("| Category | Queries |") + w("|----------|---------|") + w("| A: Exact Identifier | 6 |") + w("| B: Regex Pattern | 6 |") + w("| C: Semantic Intent | 10 |") + w("| D: Cross-File Pattern Discovery | 5 |") + w("| E: Edge Cases | 3 |") + w("") + + for cat_key in CATEGORY_ORDER: + cat_title = CATEGORY_TITLES[cat_key] + cat_metrics = [m for m in metrics if m["category"] == cat_key] + if not cat_metrics: + continue + + w(f"## {cat_title}\n") + + if cat_key == "regex_pattern": + w("> `rtk rgai` does not support regex; misses are EXPECTED_UNSUPPORTED.\n") + if cat_key == "semantic_intent": + w("> For multi-concept queries, grep exact-substring misses are expected and shown as MISS.\n") + if cat_key == "edge_case": + w("> Edge cases are discussed per-case; no category-level winner is inferred.\n") + + w("| ID | Query | Tool | Bytes | Tokens | TE | Result Count | Gold Hit | Timing (med) | Status |") + w("|----|-------|------|-------|--------|----|-------------|----------|-------------|--------|") + + for m in cat_metrics: + for tool in TOOLS: + if f"{tool}_bytes" not in m: + continue + + miss = m.get(f"{tool}_miss", False) + unsupported = m.get(f"{tool}_unsupported", False) + unexpected_hit = m.get(f"{tool}_unexpected_hit", False) + valid = m.get(f"{tool}_valid", False) + min_required = m.get(f"{tool}_gold_min_required", 0) + low_coverage = m.get(f"{tool}_low_coverage", False) + + if unsupported: + status = "EXPECTED_UNSUPPORTED" + elif not valid: + status = "INVALID" + elif miss: + status = "**MISS**" + elif unexpected_hit: + status = "**UNEXPECTED_HIT**" + elif low_coverage: + status = "LOW_COVERAGE" + else: + status = "OK" + + w( + f"| {m['test_id']} | {m['query']} | {tool} | {m[f'{tool}_bytes']:.0f} | " + f"{m.get(f'{tool}_tokens', 0):.0f} | " + f"{format_te(m.get(f'{tool}_te'), miss)} | " + f"{m.get(f'{tool}_count', 0):.0f} | " + f"{format_gold(m.get(f'{tool}_gold_hit'), m.get(f'{tool}_gold_found', 0), min_required)} | " + f"{format_timing(m.get(f'{tool}_time_us', 0.0))} | {status} |" + ) + w("") + + if cat_key != "edge_case": + w(f"### {cat_title} — Summary\n") + for tool in TOOLS: + st = category_tool_stats(cat_metrics, tool) + if st["unsupported_count"] == len(cat_metrics): + w(f"- **{tool}**: expected unsupported for this category.") + continue + + parts = [f"**{tool}**:"] + if st["te_vals"]: + parts.append( + "TE min/med/max=" + f"{min_val(st['te_vals']):.3f}/" + f"{median_val(st['te_vals']):.3f}/" + f"{max_val(st['te_vals']):.3f}" + ) + if st["gold_vals"]: + parts.append( + "gold hit min/med/max=" + f"{min_val(st['gold_vals']) * 100:.0f}%/" + f"{median_val(st['gold_vals']) * 100:.0f}%/" + f"{max_val(st['gold_vals']) * 100:.0f}%" + ) + if st["time_vals"]: + parts.append( + "time min/med/max=" + + format_timing_range( + min_val(st["min_time_vals"]), + median_val(st["time_vals"]), + max_val(st["max_time_vals"]), + ) + ) + if st["miss_count"] > 0: + parts.append(f"MISS={st['miss_count']}") + if st["unexpected_count"] > 0: + parts.append(f"UNEXPECTED_HIT={st['unexpected_count']}") + if st["low_cov_count"] > 0: + parts.append(f"LOW_COVERAGE={st['low_cov_count']}") + w("- " + " | ".join(parts)) + w("") + + # Tool recommendation rows without cross-category averaging. + w("## Summary: When to Use Which Tool\n") + w("| Situation | Recommended | Evidence |") + w("|-----------|-------------|----------|") + + cat_a = [m for m in metrics if m["category"] == "exact_identifier"] + cat_d = [m for m in metrics if m["category"] == "cross_file"] + cat_c = [m for m in metrics if m["category"] == "semantic_intent"] + cat_e = [m for m in metrics if m["category"] == "edge_case"] + + best_a, ev_a = pick_best_for_exact(cat_a) + best_d, ev_d = pick_best_for_exact(cat_d) + best_c, ev_c = pick_best_for_semantic(cat_c) + + w(f"| Exact identifier search (Category A) | {best_a} | {ev_a} |") + w(f"| Cross-file pattern discovery (Category D) | {best_d} | {ev_d} |") + w(f"| Semantic intent search (Category C) | {best_c} | {ev_c} |") + w("| Regex patterns (Category B) | grep / rtk grep | `rtk rgai` expected unsupported for regex |") + + # Edge evidence: E3 should be zero results. + e3 = next((m for m in cat_e if m["test_id"] == "E3"), None) + if e3: + bad_tools = [t for t in TOOLS if e3.get(f"{t}_unexpected_hit", False)] + if bad_tools: + w( + "| Exact zero-result validation (E3) | grep / rtk grep | " + f"Unexpected hits observed for: {', '.join(bad_tools)} |" + ) + else: + w("| Exact zero-result validation (E3) | all tools | All returned zero results as expected |") + w("") + + w("## Failure Modes\n") + w("### grep") + w("- Floods output on broad/common queries.") + w("- Misses semantic intent queries that do not appear as exact substrings.") + w("- No built-in grouping/truncation.\n") + w("### rtk grep") + w("- Output truncation (`--max 200`) can reduce recall in high-frequency queries.") + w("- Still exact-match based (no semantic expansion).\n") + w("### rtk rgai") + w("- Regex queries are unsupported by design.") + w("- Can return semantically related content even when strict zero results are expected.") + w("- Quality depends on ranking/model behavior and may vary by environment.\n") + if "head_n" in TOOLS: + w("### head_n (negative control)") + w("- Naive truncation may look token-efficient but is relevance-blind.") + w("- Useful as a floor comparator, not as a production recommendation.\n") + + w("## Limitations\n") + w("- Single codebase benchmark (`src/` Rust files only).") + w("- Gold standards are author-defined and include subjective intent mapping.") + w("- Gold hit is computed from first-run samples; non-deterministic tools may vary across runs.") + w("- Timing is hardware and background-load dependent.") + w("") + + return "\n".join(lines) + + +def main(): + if not CSV_PATH.exists(): + print(f"ERROR: {CSV_PATH} not found. Run bench_code.sh first.", file=sys.stderr) + sys.exit(1) + if not GOLD_PATH.exists(): + print(f"ERROR: {GOLD_PATH} not found.", file=sys.stderr) + sys.exit(1) + + gold_queries, gold_meta = load_gold_standards() + gold_auto = load_gold_auto() # ADDED: auto-generated gold from grep output + rows = load_csv() + env_text = ENV_PATH.read_text() if ENV_PATH.exists() else "" + env_commit = parse_commit_from_env(env_text) + pinned_commit = gold_meta.get("pinned_commit", "unknown") + + print(f"Loaded {len(rows)} measurements from {CSV_PATH}") + print(f"Loaded {len(gold_queries)} gold standards from {GOLD_PATH}") + if gold_auto: + print(f"Loaded {len(gold_auto)} auto-generated gold entries from {GOLD_AUTO_PATH}") # ADDED + + metrics = compute_metrics(rows, gold_queries, gold_auto) # CHANGED: pass gold_auto + report = generate_report(metrics, env_text, gold_queries, pinned_commit, env_commit) + RESULTS_PATH.write_text(report, encoding="utf-8") + + miss_count = 0 + unexpected_count = 0 + for m in metrics: + for tool in TOOLS: + if m.get(f"{tool}_miss", False): + miss_count += 1 + if m.get(f"{tool}_unexpected_hit", False): + unexpected_count += 1 + + print(f"\nReport written to {RESULTS_PATH}") + print(f" {len(metrics)} queries analyzed") + print(f" MISS entries: {miss_count}") + print(f" UNEXPECTED_HIT entries: {unexpected_count}") + + +if __name__ == "__main__": + main() diff --git a/benchmarks/bench_code.sh b/benchmarks/bench_code.sh new file mode 100755 index 0000000..1df8949 --- /dev/null +++ b/benchmarks/bench_code.sh @@ -0,0 +1,367 @@ +#!/usr/bin/env bash +# +# Benchmark runner: grep vs rtk grep vs rtk rgai on rtk codebase +# +# Usage: +# bash benchmarks/bench_code.sh +# +# Output: +# benchmarks/results_raw.csv — raw measurements (30 queries × 4 tools × 5 runs) # CHANGED: 4 tools +# benchmarks/results_env.txt — environment snapshot +# benchmarks/quality_samples/ — first-run full output samples (no truncation) +# benchmarks/gold_auto.json — auto-generated gold files from grep output +# +set -euo pipefail +export LC_ALL=C + +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" +SRC_DIR="$PROJECT_DIR/src" +GOLD_PATH="$SCRIPT_DIR/gold_standards.json" +CSV_OUT="$SCRIPT_DIR/results_raw.csv" +ENV_OUT="$SCRIPT_DIR/results_env.txt" +QUALITY_DIR="$SCRIPT_DIR/quality_samples" +GOLD_AUTO="$SCRIPT_DIR/gold_auto.json" # ADDED: auto-generated gold + +RUNS=5 +HEAD_N_LINES="${HEAD_N_LINES:-100}" # ADDED: negative control truncation threshold +TOKENIZER_ENCODING="${TOKENIZER_ENCODING:-cl100k_base}" +RTK_BIN="${RTK_BIN:-$PROJECT_DIR/target/release/rtk}" +ALLOW_DIRTY="${ALLOW_DIRTY:-0}" +RTK_GREP_MAX="${RTK_GREP_MAX:-200}" +RGAI_MAX="${RGAI_MAX:-8}" + +# ── Pre-flight checks ──────────────────────────────────────────────────── # + +if [ ! -d "$SRC_DIR" ]; then + echo "ERROR: src/ directory not found at $SRC_DIR" >&2 + exit 1 +fi + +if [ ! -f "$GOLD_PATH" ]; then + echo "ERROR: gold_standards.json not found at $GOLD_PATH" >&2 + exit 1 +fi + +if [ ! -x "$RTK_BIN" ]; then + echo "ERROR: rtk binary not found or not executable at $RTK_BIN" >&2 + echo "Build local binary first: cargo build --release" >&2 + exit 1 +fi + +if ! python3 - "$TOKENIZER_ENCODING" <<'PY' +import sys +import tiktoken + +enc = sys.argv[1] +tiktoken.get_encoding(enc) +PY +then + echo "ERROR: Python package 'tiktoken' is required for token-based TE." >&2 + echo "Install it with: python3 -m pip install tiktoken" >&2 + exit 1 +fi + +# ── Pin commit for reproducibility ──────────────────────────────────────── # + +EXPECTED_COMMIT="$(python3 -c "import json;print(json.load(open('$GOLD_PATH', encoding='utf-8'))['metadata']['pinned_commit'])")" +PINNED_COMMIT="$(cd "$PROJECT_DIR" && git rev-parse HEAD)" +if [ "$PINNED_COMMIT" != "$EXPECTED_COMMIT" ]; then + echo "ERROR: Current HEAD ($PINNED_COMMIT) does not match pinned commit in gold_standards.json ($EXPECTED_COMMIT)." >&2 + echo "Checkout pinned commit first for reproducible results." >&2 + exit 2 +fi + +echo "Pinned commit: $PINNED_COMMIT" + +if [ "$ALLOW_DIRTY" != "1" ]; then + if ! (cd "$PROJECT_DIR" && git diff --quiet -- src Cargo.toml Cargo.lock && git diff --cached --quiet -- src Cargo.toml Cargo.lock); then + echo "ERROR: Working tree has local changes in benchmarked sources (src/, Cargo.toml, Cargo.lock)." >&2 + echo "Commit/stash changes for auditable reproducibility, or set ALLOW_DIRTY=1 to override." >&2 + exit 3 + fi + if [ -n "$(cd "$PROJECT_DIR" && git ls-files --others --exclude-standard -- src)" ]; then + echo "ERROR: Untracked files exist under src/; benchmark dataset is not clean." >&2 + echo "Commit/remove untracked source files, or set ALLOW_DIRTY=1 to override." >&2 + exit 3 + fi +fi + +# ── Environment snapshot ────────────────────────────────────────────────── # + +{ + echo "Date: $(date -u)" + echo "Commit: $PINNED_COMMIT" + echo "rtk_bin: $RTK_BIN" + echo "rtk: $($RTK_BIN --version 2>&1 || echo 'N/A')" + echo "grep: $(grep --version 2>&1 | head -1 || echo 'N/A')" + echo "tiktoken_encoding: $TOKENIZER_ENCODING" + echo "rtk_grep_max: $RTK_GREP_MAX" + echo "rgai_max: $RGAI_MAX" + echo "head_n_lines: $HEAD_N_LINES" # ADDED: negative control param + echo "OS: $(uname -a)" + if [[ "$(uname)" == "Darwin" ]]; then + echo "CPU: $(sysctl -n machdep.cpu.brand_string 2>/dev/null || echo 'N/A')" + else + echo "CPU: $(lscpu 2>/dev/null | grep 'Model name' | sed 's/.*: *//' || echo 'N/A')" + fi + echo "Rust files: $(find "$SRC_DIR" -name '*.rs' | wc -l | tr -d ' ')" + echo "Total LOC: $(find "$SRC_DIR" -name '*.rs' -exec cat {} + | wc -l | tr -d ' ')" +} > "$ENV_OUT" + +echo "=== Environment ===" +cat "$ENV_OUT" +echo "" + +# ── Warmup (populate OS page cache) ────────────────────────────────────── # + +echo "Warming up filesystem cache..." +find "$SRC_DIR" -name '*.rs' -exec cat {} + > /dev/null 2>&1 +echo "" + +# ── Command runner helper ───────────────────────────────────────────────── # +# Prints: time_us,output_bytes,output_tokens,result_count,exit_code + +count_tokens_tiktoken() { + local out_file="$1" + python3 - "$out_file" "$TOKENIZER_ENCODING" <<'PY' +import sys +from pathlib import Path +import tiktoken + +path = Path(sys.argv[1]) +encoding_name = sys.argv[2] +enc = tiktoken.get_encoding(encoding_name) +text = path.read_text(encoding="utf-8", errors="replace") +print(len(enc.encode(text))) +PY +} + +run_command_capture() { + local out_file="$1" + shift + + local time_file elapsed_s time_us bytes tokens lines exit_code + time_file="$(mktemp)" + + TIMEFORMAT='%R' + set +e + { time "$@" > "$out_file" 2>/dev/null; } 2> "$time_file" + exit_code=$? + set -e + + elapsed_s="$(tr -d ' \t\r\n' < "$time_file")" + rm -f "$time_file" + + if [[ "$elapsed_s" =~ ^[0-9]+([.][0-9]+)?$ ]]; then + time_us="$(awk -v s="$elapsed_s" 'BEGIN { printf "%.0f", s * 1000000 }')" + else + time_us=0 + fi + + bytes=$(wc -c < "$out_file" | tr -d ' ') + tokens=$(count_tokens_tiktoken "$out_file") + lines=$(wc -l < "$out_file" | tr -d ' ') + echo "${time_us},${bytes},${tokens},${lines},${exit_code}" +} + +# ── Quality sample capture ──────────────────────────────────────────────── # + +mkdir -p "$QUALITY_DIR" +rm -f "$QUALITY_DIR"/*.txt + +# ── Test matrix ─────────────────────────────────────────────────────────── # +# Fields: test_id category query grep_flags + +declare -a TEST_IDS=() +declare -a TEST_CATEGORIES=() +declare -a TEST_QUERIES=() +declare -a TEST_GREP_FLAGS=() + +add_test() { + TEST_IDS+=("$1") + TEST_CATEGORIES+=("$2") + TEST_QUERIES+=("$3") + TEST_GREP_FLAGS+=("$4") +} + +# Category A: Exact Identifier +add_test "A1" "exact_identifier" "TimedExecution" "" +add_test "A2" "exact_identifier" "FilterLevel" "" +add_test "A3" "exact_identifier" "classify_command" "" +add_test "A4" "exact_identifier" "package_manager_exec" "" +add_test "A5" "exact_identifier" "strip_ansi" "" +add_test "A6" "exact_identifier" "HISTORY_DAYS" "" + +# Category B: Regex Pattern +add_test "B1" "regex_pattern" 'fn run\(.*verbose: u8' "-E" +add_test "B2" "regex_pattern" 'timer\.track\(' "-E" +add_test "B3" "regex_pattern" '\.unwrap_or\(1\)' "-E" +add_test "B4" "regex_pattern" '#\[cfg\(test\)\]' "-E" +add_test "B5" "regex_pattern" 'HashMap 0" "" +add_test "D2" "cross_file" "anyhow::Result" "" +add_test "D3" "cross_file" "process::exit" "" +add_test "D4" "cross_file" "Command::new" "" +add_test "D5" "cross_file" "from_utf8_lossy" "" + +# Category E: Edge Cases +add_test "E1" "edge_case" "the" "" +add_test "E2" "edge_case" "fn" "" +add_test "E3" "edge_case" "error handling retry backoff" "" + +# ── CSV header ──────────────────────────────────────────────────────────── # + +echo "test_id,category,query,tool,run,time_us,output_bytes,output_tokens,result_count,exit_code" > "$CSV_OUT" + +# ── Run matrix ──────────────────────────────────────────────────────────── # + +NUM_TESTS=${#TEST_IDS[@]} +echo "Running $NUM_TESTS tests × 4 tools × $RUNS runs = $(( NUM_TESTS * 4 * RUNS )) measurements" # CHANGED: 4 tools +echo "" + +for idx in $(seq 0 $(( NUM_TESTS - 1 ))); do + tid="${TEST_IDS[$idx]}" + category="${TEST_CATEGORIES[$idx]}" + query="${TEST_QUERIES[$idx]}" + grep_flags="${TEST_GREP_FLAGS[$idx]}" + + echo "[$tid] query=\"$query\"" + + for run in $(seq 1 $RUNS); do + tmp_grep="$(mktemp)" + tmp_rtk_grep="$(mktemp)" + tmp_rtk_rgai="$(mktemp)" + tmp_head_n="$(mktemp)" # ADDED: negative control + + grep_flag_arr=() + if [ -n "$grep_flags" ]; then + read -r -a grep_flag_arr <<< "$grep_flags" + fi + + # grep + grep_cmd=(grep -rn "${grep_flag_arr[@]}" -- "$query" "$SRC_DIR") + IFS=',' read -r grep_time grep_bytes grep_tokens grep_lines grep_exit < <(run_command_capture "$tmp_grep" "${grep_cmd[@]}") + echo "$tid,$category,\"$query\",grep,$run,$grep_time,$grep_bytes,$grep_tokens,$grep_lines,$grep_exit" >> "$CSV_OUT" + + if [ "$run" -eq 1 ]; then + cp "$tmp_grep" "$QUALITY_DIR/${tid}_grep.txt" 2>/dev/null || true + fi + + # rtk grep + rtk_grep_cmd=("$RTK_BIN" grep "$query" "$SRC_DIR" --max "$RTK_GREP_MAX") + IFS=',' read -r rtk_grep_time rtk_grep_bytes rtk_grep_tokens rtk_grep_lines rtk_grep_exit < <(run_command_capture "$tmp_rtk_grep" "${rtk_grep_cmd[@]}") + echo "$tid,$category,\"$query\",rtk_grep,$run,$rtk_grep_time,$rtk_grep_bytes,$rtk_grep_tokens,$rtk_grep_lines,$rtk_grep_exit" >> "$CSV_OUT" + + if [ "$run" -eq 1 ]; then + cp "$tmp_rtk_grep" "$QUALITY_DIR/${tid}_rtk_grep.txt" 2>/dev/null || true + fi + + # rtk rgai + rtk_rgai_cmd=("$RTK_BIN" rgai --path "$SRC_DIR" --max "$RGAI_MAX" -- "$query") + IFS=',' read -r rtk_rgai_time rtk_rgai_bytes rtk_rgai_tokens rtk_rgai_lines rtk_rgai_exit < <(run_command_capture "$tmp_rtk_rgai" "${rtk_rgai_cmd[@]}") + echo "$tid,$category,\"$query\",rtk_rgai,$run,$rtk_rgai_time,$rtk_rgai_bytes,$rtk_rgai_tokens,$rtk_rgai_lines,$rtk_rgai_exit" >> "$CSV_OUT" + + if [ "$run" -eq 1 ]; then + cp "$tmp_rtk_rgai" "$QUALITY_DIR/${tid}_rtk_rgai.txt" 2>/dev/null || true + fi + + # head_n (NEGATIVE CONTROL) ────────────────────────────────── # ADDED: entire section + # Naive truncation baseline: just take first N lines of grep output + head -n "$HEAD_N_LINES" "$tmp_grep" > "$tmp_head_n" 2>/dev/null || true + head_n_tokens=$(count_tokens_tiktoken "$tmp_head_n") + head_n_bytes=$(wc -c < "$tmp_head_n" | tr -d ' ') + head_n_lines=$(wc -l < "$tmp_head_n" | tr -d ' ') + # Timing is negligible for head, use 0 + echo "$tid,$category,\"$query\",head_n,$run,0,$head_n_bytes,$head_n_tokens,$head_n_lines,0" >> "$CSV_OUT" + + if [ "$run" -eq 1 ]; then + cp "$tmp_head_n" "$QUALITY_DIR/${tid}_head_n.txt" 2>/dev/null || true + fi + + rm -f "$tmp_grep" "$tmp_rtk_grep" "$tmp_rtk_rgai" "$tmp_head_n" # CHANGED: added tmp_head_n + done + echo " done ($RUNS runs)" +done + +echo "" +echo "=== Generating Auto Gold Standards ===" # ADDED: entire section + +# Generate gold_auto.json from grep output (automatic verification) +python3 - "$QUALITY_DIR" "$GOLD_AUTO" "$PINNED_COMMIT" << 'PYEOF' +import json +import re +import sys +from pathlib import Path + +quality_dir = Path(sys.argv[1]) +output_path = Path(sys.argv[2]) +pinned_commit = sys.argv[3] + +def extract_rs_files(text: str) -> list[str]: + """Extract unique .rs filenames from grep output.""" + files = set() + for match in re.finditer(r"([A-Za-z0-9_./-]+\.rs)", text): + path = match.group(1) + # Normalize: strip src/ prefix, keep nested paths + if "/src/" in path: + path = path.split("/src/", 1)[1] + elif path.startswith("src/"): + path = path[4:] + path = path.lstrip("./") + if path.endswith(".rs"): + files.add(path) + return sorted(files) + +gold_auto = { + "metadata": { + "description": "Auto-generated gold standards from grep output", + "pinned_commit": pinned_commit, + "generated": "auto", + "notes": "Gold files extracted automatically from grep results - no manual curation" + }, + "queries": {} +} + +# Process each grep sample +for grep_file in sorted(quality_dir.glob("*_grep.txt")): + tid = grep_file.stem.replace("_grep", "") + text = grep_file.read_text(errors="replace") + gold_files = extract_rs_files(text) + + gold_auto["queries"][tid] = { + "gold_files_auto": gold_files, + "gold_file_count": len(gold_files), + "grep_lines": len(text.splitlines()), + "grep_bytes": len(text.encode("utf-8")) + } + +output_path.write_text(json.dumps(gold_auto, indent=2), encoding="utf-8") +print(f"Generated {output_path} with {len(gold_auto['queries'])} queries") +PYEOF + +echo "" +echo "=== Benchmark Complete ===" +echo "Raw results: $CSV_OUT" +echo "Quality samples: $QUALITY_DIR/" +echo "Auto gold: $GOLD_AUTO" # ADDED +echo "Environment: $ENV_OUT" +echo "" +echo "Total measurements: $(( $(wc -l < "$CSV_OUT") - 1 ))" +echo "" +echo "Next step: python3 benchmarks/analyze_code.py" diff --git a/benchmarks/gold_standards.json b/benchmarks/gold_standards.json new file mode 100644 index 0000000..d74610d --- /dev/null +++ b/benchmarks/gold_standards.json @@ -0,0 +1,285 @@ +{ + "metadata": { + "description": "Gold standards for code-search benchmark on rtk codebase", + "pinned_commit": "4b0a413562c775757d5bc09a6ff966b4e532508c", + "codebase": "rtk-ai/rtk", + "generated": "2026-02-15", + "notes": "Gold files verified by grep on pinned commit. gold_min_files = minimum unique .rs files expected in output." + }, + "queries": { + "A1": { + "query": "TimedExecution", + "category": "exact_identifier", + "grep_flags": "", + "gold_files": ["tracking.rs", "main.rs", "cargo_cmd.rs", "git.rs", "container.rs", "grep_cmd.rs", "npm_cmd.rs", "go_cmd.rs", "gh_cmd.rs", "ls.rs"], + "gold_min_files": 30, + "expect_results": true, + "notes": "Struct def + all usages across 34 command modules" + }, + "A2": { + "query": "FilterLevel", + "category": "exact_identifier", + "grep_flags": "", + "gold_files": ["filter.rs", "main.rs", "read.rs"], + "gold_min_files": 3, + "expect_results": true, + "notes": "Enum def + variants in 3 files" + }, + "A3": { + "query": "classify_command", + "category": "exact_identifier", + "grep_flags": "", + "gold_files": ["discover/registry.rs", "discover/mod.rs"], + "gold_min_files": 2, + "expect_results": true, + "notes": "Function def + caller in discover module" + }, + "A4": { + "query": "package_manager_exec", + "category": "exact_identifier", + "grep_flags": "", + "gold_files": ["utils.rs", "vitest_cmd.rs", "playwright_cmd.rs", "prettier_cmd.rs", "lint_cmd.rs"], + "gold_min_files": 5, + "expect_results": true, + "notes": "Function def in utils.rs + callers in JS tooling modules" + }, + "A5": { + "query": "strip_ansi", + "category": "exact_identifier", + "grep_flags": "", + "gold_files": ["utils.rs", "vitest_cmd.rs", "playwright_cmd.rs", "next_cmd.rs", "cargo_cmd.rs"], + "gold_min_files": 5, + "expect_results": true, + "notes": "Function def in utils.rs + callers" + }, + "A6": { + "query": "HISTORY_DAYS", + "category": "exact_identifier", + "grep_flags": "", + "gold_files": ["tracking.rs"], + "gold_min_files": 1, + "expect_results": true, + "notes": "Const def + usage in cleanup logic, single file" + }, + + "B1": { + "query": "fn run\\(.*verbose: u8", + "category": "regex_pattern", + "grep_flags": "-E", + "gold_files": ["git.rs", "cargo_cmd.rs", "npm_cmd.rs", "container.rs", "ls.rs", "tsc_cmd.rs", "vitest_cmd.rs", "pnpm_cmd.rs"], + "gold_min_files": 25, + "expect_results": true, + "notes": "All run() signatures with verbose param on same line; 27 files match. NB: go_cmd/grep_cmd/runner use run_test()/run_err() so don't match this regex." + }, + "B2": { + "query": "timer\\.track\\(", + "category": "regex_pattern", + "grep_flags": "-E", + "gold_files": ["main.rs", "git.rs", "cargo_cmd.rs", "npm_cmd.rs", "go_cmd.rs", "gh_cmd.rs", "container.rs", "curl_cmd.rs"], + "gold_min_files": 30, + "expect_results": true, + "notes": "All tracking calls; 34 files match (same scope as TimedExecution users)" + }, + "B3": { + "query": "\\.unwrap_or\\(1\\)", + "category": "regex_pattern", + "grep_flags": "-E", + "gold_files": ["main.rs", "git.rs", "cargo_cmd.rs", "container.rs", "gh_cmd.rs", "tree.rs", "npm_cmd.rs", "gain.rs"], + "gold_min_files": 15, + "expect_results": true, + "notes": "Exit code fallback pattern .code().unwrap_or(1); 20 files match" + }, + "B4": { + "query": "#\\[cfg\\(test\\)\\]", + "category": "regex_pattern", + "grep_flags": "-E", + "gold_files": ["filter.rs", "utils.rs", "discover/registry.rs", "vitest_cmd.rs", "next_cmd.rs", "playwright_cmd.rs", "runner.rs", "tsc_cmd.rs", "git.rs", "cargo_cmd.rs"], + "gold_min_files": 35, + "expect_results": true, + "notes": "Test module declarations; 41 files have #[cfg(test)] (nearly all modules)" + }, + "B5": { + "query": "HashMap 0", + "category": "cross_file", + "grep_flags": "", + "gold_files": ["main.rs", "git.rs", "cargo_cmd.rs", "npm_cmd.rs", "go_cmd.rs", "container.rs", "grep_cmd.rs", "pnpm_cmd.rs"], + "gold_min_files": 30, + "expect_results": true, + "notes": "All verbose debug logging points; 90 occurrences across 37 files (includes parser/README.md)" + }, + "D2": { + "query": "anyhow::Result", + "category": "cross_file", + "grep_flags": "", + "gold_files": ["tracking.rs", "config.rs", "discover/mod.rs", "log_cmd.rs", "diff_cmd.rs", "deps.rs", "find_cmd.rs", "env_cmd.rs", "local_llm.rs", "learn/mod.rs", "learn/report.rs"], + "gold_min_files": 11, + "expect_results": true, + "notes": "Literal 'anyhow::Result' only in 11 files with standalone import. Most files use 'use anyhow::{Context, Result}' which doesn't contain the literal substring." + }, + "D3": { + "query": "process::exit", + "category": "cross_file", + "grep_flags": "", + "gold_files": ["main.rs", "git.rs", "cargo_cmd.rs", "npm_cmd.rs", "container.rs", "gh_cmd.rs"], + "gold_min_files": 15, + "expect_results": true, + "notes": "All exit points across 19 files" + }, + "D4": { + "query": "Command::new", + "category": "cross_file", + "grep_flags": "", + "gold_files": ["main.rs", "git.rs", "cargo_cmd.rs", "npm_cmd.rs", "utils.rs", "go_cmd.rs", "grep_cmd.rs"], + "gold_min_files": 20, + "expect_results": true, + "notes": "All subprocess spawns across 25 files" + }, + "D5": { + "query": "from_utf8_lossy", + "category": "cross_file", + "grep_flags": "", + "gold_files": ["main.rs", "git.rs", "cargo_cmd.rs", "npm_cmd.rs", "utils.rs", "container.rs", "grep_cmd.rs"], + "gold_min_files": 25, + "expect_results": true, + "notes": "All lossy UTF-8 conversions across 29 files" + }, + + "E1": { + "query": "the", + "category": "edge_case", + "grep_flags": "", + "gold_files": [], + "gold_min_files": 0, + "expect_results": true, + "notes": "Stop word: grep/rtk grep flood output; rgai should filter or return minimal" + }, + "E2": { + "query": "fn", + "category": "edge_case", + "grep_flags": "", + "gold_files": [], + "gold_min_files": 0, + "expect_results": true, + "notes": "Ultra-common 2-char token: every .rs file matches; tests truncation limits" + }, + "E3": { + "query": "error handling retry backoff", + "category": "edge_case", + "grep_flags": "", + "gold_files": [], + "gold_min_files": 0, + "expect_results": false, + "notes": "Zero results expected from all tools — nothing in codebase matches this phrase" + } + } +} diff --git a/benchmarks/quality_samples/A1_grep.txt b/benchmarks/quality_samples/A1_grep.txt new file mode 100644 index 0000000..7da9aa6 --- /dev/null +++ b/benchmarks/quality_samples/A1_grep.txt @@ -0,0 +1,104 @@ +/Users/andrew/Programming/rtk/src/pip_cmd.rs:15: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/pytest_cmd.rs:15: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/ls.rs:34: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/wget_cmd.rs:7: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/wget_cmd.rs:55: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/npm_cmd.rs:6: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:33: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:677: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/go_cmd.rs:35: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/go_cmd.rs:86: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/go_cmd.rs:129: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/go_cmd.rs:176: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/lint_cmd.rs:29: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/curl_cmd.rs:8: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:45: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:80: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:136: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/find_cmd.rs:33: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/golangci_cmd.rs:35: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/git.rs:40: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/git.rs:127: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/git.rs:299: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/git.rs:527: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/git.rs:583: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/git.rs:655: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/git.rs:719: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/git.rs:780: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/git.rs:865: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/git.rs:993: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/git.rs:1037: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/git.rs:1175: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/git.rs:1266: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/runner.rs:8: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/runner.rs:59: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/deps.rs:9: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:295: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:351: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:402: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:493: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/tree.rs:44: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/log_cmd.rs:11: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/log_cmd.rs:31: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/ruff_cmd.rs:32: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/grep_cmd.rs:17: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/json_cmd.rs:10: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/json_cmd.rs:32: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/read.rs:14: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/read.rs:81: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/tsc_cmd.rs:9: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/vitest_cmd.rs:223: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/tracking.rs:16://! use rtk::tracking::{TimedExecution, Tracker}; +/Users/andrew/Programming/rtk/src/tracking.rs:19://! let timer = TimedExecution::start(); +/Users/andrew/Programming/rtk/src/tracking.rs:731:/// use rtk::tracking::TimedExecution; +/Users/andrew/Programming/rtk/src/tracking.rs:733:/// let timer = TimedExecution::start(); +/Users/andrew/Programming/rtk/src/tracking.rs:739:pub struct TimedExecution { +/Users/andrew/Programming/rtk/src/tracking.rs:743:impl TimedExecution { +/Users/andrew/Programming/rtk/src/tracking.rs:753: /// use rtk::tracking::TimedExecution; +/Users/andrew/Programming/rtk/src/tracking.rs:755: /// let timer = TimedExecution::start(); +/Users/andrew/Programming/rtk/src/tracking.rs:782: /// use rtk::tracking::TimedExecution; +/Users/andrew/Programming/rtk/src/tracking.rs:784: /// let timer = TimedExecution::start(); +/Users/andrew/Programming/rtk/src/tracking.rs:819: /// use rtk::tracking::TimedExecution; +/Users/andrew/Programming/rtk/src/tracking.rs:821: /// let timer = TimedExecution::start(); +/Users/andrew/Programming/rtk/src/tracking.rs:855:/// Track a command execution (legacy function, use [`TimedExecution`] for new code). +/Users/andrew/Programming/rtk/src/tracking.rs:859:/// This function is deprecated. Use [`TimedExecution`] instead for automatic +/Users/andrew/Programming/rtk/src/tracking.rs:872:/// # use rtk::tracking::{track, TimedExecution}; +/Users/andrew/Programming/rtk/src/tracking.rs:877:/// let timer = TimedExecution::start(); +/Users/andrew/Programming/rtk/src/tracking.rs:880:#[deprecated(note = "Use TimedExecution instead")] +/Users/andrew/Programming/rtk/src/tracking.rs:983: // 5. TimedExecution::track records with exec_time > 0 +/Users/andrew/Programming/rtk/src/tracking.rs:986: let timer = TimedExecution::start(); +/Users/andrew/Programming/rtk/src/tracking.rs:996: // 6. TimedExecution::track_passthrough records with 0 tokens +/Users/andrew/Programming/rtk/src/tracking.rs:999: let timer = TimedExecution::start(); +/Users/andrew/Programming/rtk/src/main.rs:1320: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/main.rs:1337: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/main.rs:1404: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/diff_cmd.rs:9: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/diff_cmd.rs:71: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/prettier_cmd.rs:6: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/next_cmd.rs:8: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/env_cmd.rs:8: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/container.rs:28: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/container.rs:85: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/container.rs:155: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/container.rs:185: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/container.rs:286: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/container.rs:360: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/container.rs:412: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/container.rs:436: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:49: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:133: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:306: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:392: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:448: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:515: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:613: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:696: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:775: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:845: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:883: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:929: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:963: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:1015: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:1059: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/playwright_cmd.rs:220: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/summary.rs:9: let timer = tracking::TimedExecution::start(); diff --git a/benchmarks/quality_samples/A1_head_n.txt b/benchmarks/quality_samples/A1_head_n.txt new file mode 100644 index 0000000..195dc66 --- /dev/null +++ b/benchmarks/quality_samples/A1_head_n.txt @@ -0,0 +1,100 @@ +/Users/andrew/Programming/rtk/src/pip_cmd.rs:15: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/pytest_cmd.rs:15: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/ls.rs:34: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/wget_cmd.rs:7: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/wget_cmd.rs:55: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/npm_cmd.rs:6: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:33: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:677: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/go_cmd.rs:35: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/go_cmd.rs:86: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/go_cmd.rs:129: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/go_cmd.rs:176: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/lint_cmd.rs:29: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/curl_cmd.rs:8: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:45: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:80: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:136: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/find_cmd.rs:33: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/golangci_cmd.rs:35: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/git.rs:40: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/git.rs:127: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/git.rs:299: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/git.rs:527: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/git.rs:583: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/git.rs:655: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/git.rs:719: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/git.rs:780: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/git.rs:865: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/git.rs:993: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/git.rs:1037: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/git.rs:1175: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/git.rs:1266: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/runner.rs:8: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/runner.rs:59: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/deps.rs:9: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:295: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:351: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:402: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:493: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/tree.rs:44: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/log_cmd.rs:11: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/log_cmd.rs:31: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/ruff_cmd.rs:32: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/grep_cmd.rs:17: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/json_cmd.rs:10: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/json_cmd.rs:32: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/read.rs:14: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/read.rs:81: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/tsc_cmd.rs:9: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/vitest_cmd.rs:223: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/tracking.rs:16://! use rtk::tracking::{TimedExecution, Tracker}; +/Users/andrew/Programming/rtk/src/tracking.rs:19://! let timer = TimedExecution::start(); +/Users/andrew/Programming/rtk/src/tracking.rs:731:/// use rtk::tracking::TimedExecution; +/Users/andrew/Programming/rtk/src/tracking.rs:733:/// let timer = TimedExecution::start(); +/Users/andrew/Programming/rtk/src/tracking.rs:739:pub struct TimedExecution { +/Users/andrew/Programming/rtk/src/tracking.rs:743:impl TimedExecution { +/Users/andrew/Programming/rtk/src/tracking.rs:753: /// use rtk::tracking::TimedExecution; +/Users/andrew/Programming/rtk/src/tracking.rs:755: /// let timer = TimedExecution::start(); +/Users/andrew/Programming/rtk/src/tracking.rs:782: /// use rtk::tracking::TimedExecution; +/Users/andrew/Programming/rtk/src/tracking.rs:784: /// let timer = TimedExecution::start(); +/Users/andrew/Programming/rtk/src/tracking.rs:819: /// use rtk::tracking::TimedExecution; +/Users/andrew/Programming/rtk/src/tracking.rs:821: /// let timer = TimedExecution::start(); +/Users/andrew/Programming/rtk/src/tracking.rs:855:/// Track a command execution (legacy function, use [`TimedExecution`] for new code). +/Users/andrew/Programming/rtk/src/tracking.rs:859:/// This function is deprecated. Use [`TimedExecution`] instead for automatic +/Users/andrew/Programming/rtk/src/tracking.rs:872:/// # use rtk::tracking::{track, TimedExecution}; +/Users/andrew/Programming/rtk/src/tracking.rs:877:/// let timer = TimedExecution::start(); +/Users/andrew/Programming/rtk/src/tracking.rs:880:#[deprecated(note = "Use TimedExecution instead")] +/Users/andrew/Programming/rtk/src/tracking.rs:983: // 5. TimedExecution::track records with exec_time > 0 +/Users/andrew/Programming/rtk/src/tracking.rs:986: let timer = TimedExecution::start(); +/Users/andrew/Programming/rtk/src/tracking.rs:996: // 6. TimedExecution::track_passthrough records with 0 tokens +/Users/andrew/Programming/rtk/src/tracking.rs:999: let timer = TimedExecution::start(); +/Users/andrew/Programming/rtk/src/main.rs:1320: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/main.rs:1337: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/main.rs:1404: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/diff_cmd.rs:9: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/diff_cmd.rs:71: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/prettier_cmd.rs:6: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/next_cmd.rs:8: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/env_cmd.rs:8: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/container.rs:28: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/container.rs:85: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/container.rs:155: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/container.rs:185: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/container.rs:286: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/container.rs:360: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/container.rs:412: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/container.rs:436: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:49: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:133: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:306: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:392: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:448: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:515: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:613: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:696: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:775: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:845: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:883: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:929: let timer = tracking::TimedExecution::start(); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:963: let timer = tracking::TimedExecution::start(); diff --git a/benchmarks/quality_samples/A1_rtk_grep.txt b/benchmarks/quality_samples/A1_rtk_grep.txt new file mode 100644 index 0000000..dcbf9b1 --- /dev/null +++ b/benchmarks/quality_samples/A1_rtk_grep.txt @@ -0,0 +1,159 @@ +🔍 104 in 34F: + +📄 /Users/andrew/Programming/rtk/src/cargo_cmd.rs (2): + 33: let timer = tracking::TimedExecution::start(); + 677: let timer = tracking::TimedExecution::start(); + +📄 /Users/andrew/Programming/rtk/src/container.rs (8): + 28: let timer = tracking::TimedExecution::start(); + 85: let timer = tracking::TimedExecution::start(); + 155: let timer = tracking::TimedExecution::start(); + 185: let timer = tracking::TimedExecution::start(); + 286: let timer = tracking::TimedExecution::start(); + 360: let timer = tracking::TimedExecution::start(); + 412: let timer = tracking::TimedExecution::start(); + 436: let timer = tracking::TimedExecution::start(); + +📄 /Users/andrew/Programming/rtk/src/curl_cmd.rs (1): + 8: let timer = tracking::TimedExecution::start(); + +📄 /Users/andrew/Programming/rtk/src/deps.rs (1): + 9: let timer = tracking::TimedExecution::start(); + +📄 /Users/andrew/Programming/rtk/src/diff_cmd.rs (2): + 9: let timer = tracking::TimedExecution::start(); + 71: let timer = tracking::TimedExecution::start(); + +📄 /Users/andrew/Programming/rtk/src/env_cmd.rs (1): + 8: let timer = tracking::TimedExecution::start(); + +📄 /Users/andrew/Programming/rtk/src/find_cmd.rs (1): + 33: let timer = tracking::TimedExecution::start(); + +📄 /Users/andrew/Programming/rtk/src/gh_cmd.rs (15): + 49: let timer = tracking::TimedExecution::start(); + 133: let timer = tracking::TimedExecution::start(); + 306: let timer = tracking::TimedExecution::start(); + 392: let timer = tracking::TimedExecution::start(); + 448: let timer = tracking::TimedExecution::start(); + 515: let timer = tracking::TimedExecution::start(); + 613: let timer = tracking::TimedExecution::start(); + 696: let timer = tracking::TimedExecution::start(); + 775: let timer = tracking::TimedExecution::start(); + 845: let timer = tracking::TimedExecution::start(); + +5 + +📄 /Users/andrew/Programming/rtk/src/git.rs (13): + 40: let timer = tracking::TimedExecution::start(); + 127: let timer = tracking::TimedExecution::start(); + 299: let timer = tracking::TimedExecution::start(); + 527: let timer = tracking::TimedExecution::start(); + 583: let timer = tracking::TimedExecution::start(); + 655: let timer = tracking::TimedExecution::start(); + 719: let timer = tracking::TimedExecution::start(); + 780: let timer = tracking::TimedExecution::start(); + 865: let timer = tracking::TimedExecution::start(); + 993: let timer = tracking::TimedExecution::start(); + +3 + +📄 /Users/andrew/Programming/rtk/src/go_cmd.rs (4): + 35: let timer = tracking::TimedExecution::start(); + 86: let timer = tracking::TimedExecution::start(); + 129: let timer = tracking::TimedExecution::start(); + 176: let timer = tracking::TimedExecution::start(); + +📄 /Users/andrew/Programming/rtk/src/golangci_cmd.rs (1): + 35: let timer = tracking::TimedExecution::start(); + +📄 /Users/andrew/Programming/rtk/src/grep_cmd.rs (1): + 17: let timer = tracking::TimedExecution::start(); + +📄 /Users/andrew/Programming/rtk/src/json_cmd.rs (2): + 10: let timer = tracking::TimedExecution::start(); + 32: let timer = tracking::TimedExecution::start(); + +📄 /Users/andrew/Programming/rtk/src/lint_cmd.rs (1): + 29: let timer = tracking::TimedExecution::start(); + +📄 /Users/andrew/Programming/rtk/src/log_cmd.rs (2): + 11: let timer = tracking::TimedExecution::start(); + 31: let timer = tracking::TimedExecution::start(); + +📄 /Users/andrew/Programming/rtk/src/ls.rs (1): + 34: let timer = tracking::TimedExecution::start(); + +📄 /Users/andrew/Programming/rtk/src/main.rs (3): + 1320: let timer = tracking::TimedExecution::start(); + 1337: let timer = tracking::TimedExecution::start(); + 1404: let timer = tracking::TimedExecution::start(); + +📄 /Users/andrew/Programming/rtk/src/next_cmd.rs (1): + 8: let timer = tracking::TimedExecution::start(); + +📄 /Users/andrew/Programming/rtk/src/npm_cmd.rs (1): + 6: let timer = tracking::TimedExecution::start(); + +📄 /Users/andrew/Programming/rtk/src/pip_cmd.rs (1): + 15: let timer = tracking::TimedExecution::start(); + +📄 /.../src/playwright_cmd.rs (1): + 220: let timer = tracking::TimedExecution::start(); + +📄 /Users/andrew/Programming/rtk/src/pnpm_cmd.rs (4): + 295: let timer = tracking::TimedExecution::start(); + 351: let timer = tracking::TimedExecution::start(); + 402: let timer = tracking::TimedExecution::start(); + 493: let timer = tracking::TimedExecution::start(); + +📄 /Users/andrew/Programming/rtk/src/prettier_cmd.rs (1): + 6: let timer = tracking::TimedExecution::start(); + +📄 /Users/andrew/Programming/rtk/src/prisma_cmd.rs (3): + 45: let timer = tracking::TimedExecution::start(); + 80: let timer = tracking::TimedExecution::start(); + 136: let timer = tracking::TimedExecution::start(); + +📄 /Users/andrew/Programming/rtk/src/pytest_cmd.rs (1): + 15: let timer = tracking::TimedExecution::start(); + +📄 /Users/andrew/Programming/rtk/src/read.rs (2): + 14: let timer = tracking::TimedExecution::start(); + 81: let timer = tracking::TimedExecution::start(); + +📄 /Users/andrew/Programming/rtk/src/ruff_cmd.rs (1): + 32: let timer = tracking::TimedExecution::start(); + +📄 /Users/andrew/Programming/rtk/src/runner.rs (2): + 8: let timer = tracking::TimedExecution::start(); + 59: let timer = tracking::TimedExecution::start(); + +📄 /Users/andrew/Programming/rtk/src/summary.rs (1): + 9: let timer = tracking::TimedExecution::start(); + +📄 /Users/andrew/Programming/rtk/src/tracking.rs (21): + 16: //! use rtk::tracking::{TimedExecution, Tracker}; + 19: //! let timer = TimedExecution::start(); + 731: /// use rtk::tracking::TimedExecution; + 733: /// let timer = TimedExecution::start(); + 739: pub struct TimedExecution { + 743: impl TimedExecution { + 753: /// use rtk::tracking::TimedExecution; + 755: /// let timer = TimedExecution::start(); + 782: /// use rtk::tracking::TimedExecution; + 784: /// let timer = TimedExecution::start(); + +11 + +📄 /Users/andrew/Programming/rtk/src/tree.rs (1): + 44: let timer = tracking::TimedExecution::start(); + +📄 /Users/andrew/Programming/rtk/src/tsc_cmd.rs (1): + 9: let timer = tracking::TimedExecution::start(); + +📄 /Users/andrew/Programming/rtk/src/vitest_cmd.rs (1): + 223: let timer = tracking::TimedExecution::start(); + +📄 /Users/andrew/Programming/rtk/src/wget_cmd.rs (2): + 7: let timer = tracking::TimedExecution::start(); + 55: let timer = tracking::TimedExecution::start(); + +... +19 diff --git a/benchmarks/quality_samples/A1_rtk_rgai.txt b/benchmarks/quality_samples/A1_rtk_rgai.txt new file mode 100644 index 0000000..500badf --- /dev/null +++ b/benchmarks/quality_samples/A1_rtk_rgai.txt @@ -0,0 +1,94 @@ +🧠 34F for 'TimedExecution' (scan 55F) + +📄 tracking.rs [17.9] + 738: /// ``` + 739: pub struct TimedExecution { + 740: start: Instant, + ~ timedexecution + + 743: impl TimedExecution { + 744: /// Start timing a command execution. + ~ timedexecution + + +19 more lines + +📄 gh_cmd.rs [13.9] + 48: fn list_prs(args: &[String], _verbose: u8, ultra_compact: bool) -> Result<()> { + 49: let timer = tracking::TimedExecution::start(); + ~ timedexecution + + 132: fn view_pr(args: &[String], _verbose: u8, ultra_compact: bool) -> Result<()> { + 133: let timer = tracking::TimedExecution::start(); + ~ timedexecution + + +13 more lines + +📄 git.rs [13.8] + 39: fn run_diff(args: &[String], max_lines: Option, verbose: u8) -> Result<()> { + 40: let timer = tracking::TimedExecution::start(); + ~ timedexecution + + 126: fn run_show(args: &[String], max_lines: Option, verbose: u8) -> Result<()> { + 127: let timer = tracking::TimedExecution::start(); + ~ timedexecution + + +11 more lines + +📄 container.rs [13.4] + 27: fn docker_ps(_verbose: u8) -> Result<()> { + 28: let timer = tracking::TimedExecution::start(); + ~ timedexecution + + 84: fn docker_images(_verbose: u8) -> Result<()> { + 85: let timer = tracking::TimedExecution::start(); + ~ timedexecution + + +6 more lines + +📄 go_cmd.rs [12.8] + 34: pub fn run_test(args: &[String], verbose: u8) -> Result<()> { + 35: let timer = tracking::TimedExecution::start(); + ~ timedexecution + + 85: pub fn run_build(args: &[String], verbose: u8) -> Result<()> { + 86: let timer = tracking::TimedExecution::start(); + ~ timedexecution + + +2 more lines + +📄 pnpm_cmd.rs [12.8] + 294: fn run_list(depth: usize, args: &[String], verbose: u8) -> Result<()> { + 295: let timer = tracking::TimedExecution::start(); + ~ timedexecution + + 350: fn run_outdated(args: &[String], verbose: u8) -> Result<()> { + 351: let timer = tracking::TimedExecution::start(); + ~ timedexecution + + +2 more lines + +📄 main.rs [12.6] + 1319: // Passthrough other prisma subcommands + 1320: let timer = tracking::TimedExecution::start(); + 1321: let mut cmd = std::process::Command::new("npx"); + ~ timedexecution + + 1336: } else { + 1337: let timer = tracking::TimedExecution::start(); + 1338: let status = std::process::Command::new("npx") + ~ timedexecution + + +1 more lines + +📄 prisma_cmd.rs [12.6] + 44: fn run_generate(args: &[String], verbose: u8) -> Result<()> { + 45: let timer = tracking::TimedExecution::start(); + ~ timedexecution + + 79: fn run_migrate(subcommand: MigrateSubcommand, args: &[String], verbose: u8) -> Result<()> { + 80: let timer = tracking::TimedExecution::start(); + ~ timedexecution + + +1 more lines + +... +26F diff --git a/benchmarks/quality_samples/A2_grep.txt b/benchmarks/quality_samples/A2_grep.txt new file mode 100644 index 0000000..975f90e --- /dev/null +++ b/benchmarks/quality_samples/A2_grep.txt @@ -0,0 +1,23 @@ +/Users/andrew/Programming/rtk/src/read.rs:1:use crate::filter::{self, FilterLevel, Language}; +/Users/andrew/Programming/rtk/src/read.rs:9: level: FilterLevel, +/Users/andrew/Programming/rtk/src/read.rs:74: level: FilterLevel, +/Users/andrew/Programming/rtk/src/read.rs:163: run(file.path(), FilterLevel::Minimal, None, false, 0)?; +/Users/andrew/Programming/rtk/src/main.rs:99: level: filter::FilterLevel, +/Users/andrew/Programming/rtk/src/filter.rs:6:pub enum FilterLevel { +/Users/andrew/Programming/rtk/src/filter.rs:12:impl FromStr for FilterLevel { +/Users/andrew/Programming/rtk/src/filter.rs:17: "none" => Ok(FilterLevel::None), +/Users/andrew/Programming/rtk/src/filter.rs:18: "minimal" => Ok(FilterLevel::Minimal), +/Users/andrew/Programming/rtk/src/filter.rs:19: "aggressive" => Ok(FilterLevel::Aggressive), +/Users/andrew/Programming/rtk/src/filter.rs:25:impl std::fmt::Display for FilterLevel { +/Users/andrew/Programming/rtk/src/filter.rs:28: FilterLevel::None => write!(f, "none"), +/Users/andrew/Programming/rtk/src/filter.rs:29: FilterLevel::Minimal => write!(f, "minimal"), +/Users/andrew/Programming/rtk/src/filter.rs:30: FilterLevel::Aggressive => write!(f, "aggressive"), +/Users/andrew/Programming/rtk/src/filter.rs:309:pub fn get_filter(level: FilterLevel) -> Box { +/Users/andrew/Programming/rtk/src/filter.rs:311: FilterLevel::None => Box::new(NoFilter), +/Users/andrew/Programming/rtk/src/filter.rs:312: FilterLevel::Minimal => Box::new(MinimalFilter), +/Users/andrew/Programming/rtk/src/filter.rs:313: FilterLevel::Aggressive => Box::new(AggressiveFilter), +/Users/andrew/Programming/rtk/src/filter.rs:374: assert_eq!(FilterLevel::from_str("none").unwrap(), FilterLevel::None); +/Users/andrew/Programming/rtk/src/filter.rs:376: FilterLevel::from_str("minimal").unwrap(), +/Users/andrew/Programming/rtk/src/filter.rs:377: FilterLevel::Minimal +/Users/andrew/Programming/rtk/src/filter.rs:380: FilterLevel::from_str("aggressive").unwrap(), +/Users/andrew/Programming/rtk/src/filter.rs:381: FilterLevel::Aggressive diff --git a/benchmarks/quality_samples/A2_head_n.txt b/benchmarks/quality_samples/A2_head_n.txt new file mode 100644 index 0000000..975f90e --- /dev/null +++ b/benchmarks/quality_samples/A2_head_n.txt @@ -0,0 +1,23 @@ +/Users/andrew/Programming/rtk/src/read.rs:1:use crate::filter::{self, FilterLevel, Language}; +/Users/andrew/Programming/rtk/src/read.rs:9: level: FilterLevel, +/Users/andrew/Programming/rtk/src/read.rs:74: level: FilterLevel, +/Users/andrew/Programming/rtk/src/read.rs:163: run(file.path(), FilterLevel::Minimal, None, false, 0)?; +/Users/andrew/Programming/rtk/src/main.rs:99: level: filter::FilterLevel, +/Users/andrew/Programming/rtk/src/filter.rs:6:pub enum FilterLevel { +/Users/andrew/Programming/rtk/src/filter.rs:12:impl FromStr for FilterLevel { +/Users/andrew/Programming/rtk/src/filter.rs:17: "none" => Ok(FilterLevel::None), +/Users/andrew/Programming/rtk/src/filter.rs:18: "minimal" => Ok(FilterLevel::Minimal), +/Users/andrew/Programming/rtk/src/filter.rs:19: "aggressive" => Ok(FilterLevel::Aggressive), +/Users/andrew/Programming/rtk/src/filter.rs:25:impl std::fmt::Display for FilterLevel { +/Users/andrew/Programming/rtk/src/filter.rs:28: FilterLevel::None => write!(f, "none"), +/Users/andrew/Programming/rtk/src/filter.rs:29: FilterLevel::Minimal => write!(f, "minimal"), +/Users/andrew/Programming/rtk/src/filter.rs:30: FilterLevel::Aggressive => write!(f, "aggressive"), +/Users/andrew/Programming/rtk/src/filter.rs:309:pub fn get_filter(level: FilterLevel) -> Box { +/Users/andrew/Programming/rtk/src/filter.rs:311: FilterLevel::None => Box::new(NoFilter), +/Users/andrew/Programming/rtk/src/filter.rs:312: FilterLevel::Minimal => Box::new(MinimalFilter), +/Users/andrew/Programming/rtk/src/filter.rs:313: FilterLevel::Aggressive => Box::new(AggressiveFilter), +/Users/andrew/Programming/rtk/src/filter.rs:374: assert_eq!(FilterLevel::from_str("none").unwrap(), FilterLevel::None); +/Users/andrew/Programming/rtk/src/filter.rs:376: FilterLevel::from_str("minimal").unwrap(), +/Users/andrew/Programming/rtk/src/filter.rs:377: FilterLevel::Minimal +/Users/andrew/Programming/rtk/src/filter.rs:380: FilterLevel::from_str("aggressive").unwrap(), +/Users/andrew/Programming/rtk/src/filter.rs:381: FilterLevel::Aggressive diff --git a/benchmarks/quality_samples/A2_rtk_grep.txt b/benchmarks/quality_samples/A2_rtk_grep.txt new file mode 100644 index 0000000..09885f5 --- /dev/null +++ b/benchmarks/quality_samples/A2_rtk_grep.txt @@ -0,0 +1,25 @@ +🔍 23 in 3F: + +📄 /Users/andrew/Programming/rtk/src/filter.rs (18): + 6: pub enum FilterLevel { + 12: impl FromStr for FilterLevel { + 17: "none" => Ok(FilterLevel::None), + 18: "minimal" => Ok(FilterLevel::Minimal), + 19: "aggressive" => Ok(FilterLevel::Aggressive), + 25: impl std::fmt::Display for FilterLevel { + 28: FilterLevel::None => write!(f, "none"), + 29: FilterLevel::Minimal => write!(f, "minimal"), + 30: FilterLevel::Aggressive => write!(f, "aggressive"), + 309: pub fn get_filter(level: FilterLevel) -> Box { + +8 + +📄 /Users/andrew/Programming/rtk/src/main.rs (1): + 99: level: filter::FilterLevel, + +📄 /Users/andrew/Programming/rtk/src/read.rs (4): + 1: use crate::filter::{self, FilterLevel, Language}; + 9: level: FilterLevel, + 74: level: FilterLevel, + 163: run(file.path(), FilterLevel::Minimal, None, false, 0)?; + +... +8 diff --git a/benchmarks/quality_samples/A2_rtk_rgai.txt b/benchmarks/quality_samples/A2_rtk_rgai.txt new file mode 100644 index 0000000..7479ada --- /dev/null +++ b/benchmarks/quality_samples/A2_rtk_rgai.txt @@ -0,0 +1,32 @@ +🧠 3F for 'FilterLevel' (scan 55F) + +📄 filter.rs [17.7] + 5: #[derive(Debug, Clone, Copy, PartialEq, Eq)] + 6: pub enum FilterLevel { + 7: None, + ~ filterlevel + + 12: impl FromStr for FilterLevel { + 13: type Err = String; + ~ filterlevel + + +16 more lines + +📄 read.rs [12.8] + 1: use crate::filter::{self, FilterLevel, Language}; + 2: use crate::tracking; + ~ filterlevel + + 8: file: &Path, + 9: level: FilterLevel, + 10: max_lines: Option, + ~ filterlevel + + +2 more lines + +📄 main.rs [8.4] + 98: #[arg(short, long, default_value = "minimal")] + 99: level: filter::FilterLevel, + 100: /// Max lines + ~ filterlevel + diff --git a/benchmarks/quality_samples/A3_grep.txt b/benchmarks/quality_samples/A3_grep.txt new file mode 100644 index 0000000..c2c57b8 --- /dev/null +++ b/benchmarks/quality_samples/A3_grep.txt @@ -0,0 +1,22 @@ +/Users/andrew/Programming/rtk/src/discover/registry.rs:314:pub fn classify_command(cmd: &str) -> Classification { +/Users/andrew/Programming/rtk/src/discover/registry.rs:513: classify_command("git status"), +/Users/andrew/Programming/rtk/src/discover/registry.rs:526: classify_command("git diff --cached"), +/Users/andrew/Programming/rtk/src/discover/registry.rs:539: classify_command("cargo test filter::"), +/Users/andrew/Programming/rtk/src/discover/registry.rs:552: classify_command("npx tsc --noEmit"), +/Users/andrew/Programming/rtk/src/discover/registry.rs:565: classify_command("cat src/main.rs"), +/Users/andrew/Programming/rtk/src/discover/registry.rs:578: classify_command("grepai search auth middleware"), +/Users/andrew/Programming/rtk/src/discover/registry.rs:591: classify_command("rgai auth middleware"), +/Users/andrew/Programming/rtk/src/discover/registry.rs:603: assert_eq!(classify_command("cd /tmp"), Classification::Ignored); +/Users/andrew/Programming/rtk/src/discover/registry.rs:608: assert_eq!(classify_command("rtk git status"), Classification::Ignored); +/Users/andrew/Programming/rtk/src/discover/registry.rs:614: classify_command("echo hello world"), +/Users/andrew/Programming/rtk/src/discover/registry.rs:621: match classify_command("terraform plan -var-file=prod.tfvars") { +/Users/andrew/Programming/rtk/src/discover/registry.rs:632: classify_command("GIT_SSH_COMMAND=ssh git push"), +/Users/andrew/Programming/rtk/src/discover/registry.rs:645: classify_command("sudo docker ps"), +/Users/andrew/Programming/rtk/src/discover/registry.rs:658: classify_command("cargo check"), +/Users/andrew/Programming/rtk/src/discover/registry.rs:671: classify_command("cargo check --all-targets"), +/Users/andrew/Programming/rtk/src/discover/registry.rs:684: classify_command("cargo fmt"), +/Users/andrew/Programming/rtk/src/discover/registry.rs:697: classify_command("cargo clippy --all-targets"), +/Users/andrew/Programming/rtk/src/discover/registry.rs:722: match classify_command(&cmd) { +/Users/andrew/Programming/rtk/src/discover/registry.rs:737: match classify_command(&cmd) { +/Users/andrew/Programming/rtk/src/discover/mod.rs:9:use registry::{category_avg_tokens, classify_command, split_command_chain, Classification}; +/Users/andrew/Programming/rtk/src/discover/mod.rs:84: match classify_command(part) { diff --git a/benchmarks/quality_samples/A3_head_n.txt b/benchmarks/quality_samples/A3_head_n.txt new file mode 100644 index 0000000..c2c57b8 --- /dev/null +++ b/benchmarks/quality_samples/A3_head_n.txt @@ -0,0 +1,22 @@ +/Users/andrew/Programming/rtk/src/discover/registry.rs:314:pub fn classify_command(cmd: &str) -> Classification { +/Users/andrew/Programming/rtk/src/discover/registry.rs:513: classify_command("git status"), +/Users/andrew/Programming/rtk/src/discover/registry.rs:526: classify_command("git diff --cached"), +/Users/andrew/Programming/rtk/src/discover/registry.rs:539: classify_command("cargo test filter::"), +/Users/andrew/Programming/rtk/src/discover/registry.rs:552: classify_command("npx tsc --noEmit"), +/Users/andrew/Programming/rtk/src/discover/registry.rs:565: classify_command("cat src/main.rs"), +/Users/andrew/Programming/rtk/src/discover/registry.rs:578: classify_command("grepai search auth middleware"), +/Users/andrew/Programming/rtk/src/discover/registry.rs:591: classify_command("rgai auth middleware"), +/Users/andrew/Programming/rtk/src/discover/registry.rs:603: assert_eq!(classify_command("cd /tmp"), Classification::Ignored); +/Users/andrew/Programming/rtk/src/discover/registry.rs:608: assert_eq!(classify_command("rtk git status"), Classification::Ignored); +/Users/andrew/Programming/rtk/src/discover/registry.rs:614: classify_command("echo hello world"), +/Users/andrew/Programming/rtk/src/discover/registry.rs:621: match classify_command("terraform plan -var-file=prod.tfvars") { +/Users/andrew/Programming/rtk/src/discover/registry.rs:632: classify_command("GIT_SSH_COMMAND=ssh git push"), +/Users/andrew/Programming/rtk/src/discover/registry.rs:645: classify_command("sudo docker ps"), +/Users/andrew/Programming/rtk/src/discover/registry.rs:658: classify_command("cargo check"), +/Users/andrew/Programming/rtk/src/discover/registry.rs:671: classify_command("cargo check --all-targets"), +/Users/andrew/Programming/rtk/src/discover/registry.rs:684: classify_command("cargo fmt"), +/Users/andrew/Programming/rtk/src/discover/registry.rs:697: classify_command("cargo clippy --all-targets"), +/Users/andrew/Programming/rtk/src/discover/registry.rs:722: match classify_command(&cmd) { +/Users/andrew/Programming/rtk/src/discover/registry.rs:737: match classify_command(&cmd) { +/Users/andrew/Programming/rtk/src/discover/mod.rs:9:use registry::{category_avg_tokens, classify_command, split_command_chain, Classification}; +/Users/andrew/Programming/rtk/src/discover/mod.rs:84: match classify_command(part) { diff --git a/benchmarks/quality_samples/A3_rtk_grep.txt b/benchmarks/quality_samples/A3_rtk_grep.txt new file mode 100644 index 0000000..a18cdd9 --- /dev/null +++ b/benchmarks/quality_samples/A3_rtk_grep.txt @@ -0,0 +1,20 @@ +🔍 22 in 2F: + +📄 /Users/andrew/Programming/rtk/src/discover/mod.rs (2): + 9: ...ry::{category_avg_tokens, classify_command, split_command_chain, Classification}... + 84: match classify_command(part) { + +📄 /.../discover/registry.rs (20): + 314: pub fn classify_command(cmd: &str) -> Classification { + 513: classify_command("git status"), + 526: classify_command("git diff --cached"), + 539: classify_command("cargo test filter::"), + 552: classify_command("npx tsc --noEmit"), + 565: classify_command("cat src/main.rs"), + 578: classify_command("grepai search auth middleware"), + 591: classify_command("rgai auth middleware"), + 603: assert_eq!(classify_command("cd /tmp"), Classification::Ignored); + 608: assert_eq!(classify_command("rtk git status"), Classification::Ignored); + +10 + +... +10 diff --git a/benchmarks/quality_samples/A3_rtk_rgai.txt b/benchmarks/quality_samples/A3_rtk_rgai.txt new file mode 100644 index 0000000..374c1bb --- /dev/null +++ b/benchmarks/quality_samples/A3_rtk_rgai.txt @@ -0,0 +1,25 @@ +🧠 2F for 'classify_command' (scan 55F) + +📄 discover/registry.rs [16.7] + 313: /// Classify a single (already-split) command. + 314: pub fn classify_command(cmd: &str) -> Classification { + 315: let trimmed = cmd.trim(); + ~ classify_command + + 512: assert_eq!( + 513: classify_command("git status"), + 514: Classification::Supported { + ~ classify_command + + +18 more lines + +📄 discover/mod.rs [12.3] + 8: use provider::{ClaudeProvider, SessionProvider}; + 9: use registry::{category_avg_tokens, classify_command, split_command_chain, Classification}; + 10: use report::{DiscoverReport, SupportedEntry, UnsupportedEntry}; + ~ classify_command + + 84: match classify_command(part) { + 85: Classification::Supported { + ~ classify_command + diff --git a/benchmarks/quality_samples/A4_grep.txt b/benchmarks/quality_samples/A4_grep.txt new file mode 100644 index 0000000..6a34f45 --- /dev/null +++ b/benchmarks/quality_samples/A4_grep.txt @@ -0,0 +1,9 @@ +/Users/andrew/Programming/rtk/src/lint_cmd.rs:2:use crate::utils::{package_manager_exec, truncate}; +/Users/andrew/Programming/rtk/src/lint_cmd.rs:39: let mut cmd = package_manager_exec(linter); +/Users/andrew/Programming/rtk/src/vitest_cmd.rs:10:use crate::utils::{package_manager_exec, strip_ansi}; +/Users/andrew/Programming/rtk/src/vitest_cmd.rs:225: let mut cmd = package_manager_exec("vitest"); +/Users/andrew/Programming/rtk/src/prettier_cmd.rs:2:use crate::utils::package_manager_exec; +/Users/andrew/Programming/rtk/src/prettier_cmd.rs:8: let mut cmd = package_manager_exec("prettier"); +/Users/andrew/Programming/rtk/src/utils.rs:197:pub fn package_manager_exec(tool: &str) -> Command { +/Users/andrew/Programming/rtk/src/playwright_cmd.rs:2:use crate::utils::{package_manager_exec, strip_ansi}; +/Users/andrew/Programming/rtk/src/playwright_cmd.rs:222: let mut cmd = package_manager_exec("playwright"); diff --git a/benchmarks/quality_samples/A4_head_n.txt b/benchmarks/quality_samples/A4_head_n.txt new file mode 100644 index 0000000..6a34f45 --- /dev/null +++ b/benchmarks/quality_samples/A4_head_n.txt @@ -0,0 +1,9 @@ +/Users/andrew/Programming/rtk/src/lint_cmd.rs:2:use crate::utils::{package_manager_exec, truncate}; +/Users/andrew/Programming/rtk/src/lint_cmd.rs:39: let mut cmd = package_manager_exec(linter); +/Users/andrew/Programming/rtk/src/vitest_cmd.rs:10:use crate::utils::{package_manager_exec, strip_ansi}; +/Users/andrew/Programming/rtk/src/vitest_cmd.rs:225: let mut cmd = package_manager_exec("vitest"); +/Users/andrew/Programming/rtk/src/prettier_cmd.rs:2:use crate::utils::package_manager_exec; +/Users/andrew/Programming/rtk/src/prettier_cmd.rs:8: let mut cmd = package_manager_exec("prettier"); +/Users/andrew/Programming/rtk/src/utils.rs:197:pub fn package_manager_exec(tool: &str) -> Command { +/Users/andrew/Programming/rtk/src/playwright_cmd.rs:2:use crate::utils::{package_manager_exec, strip_ansi}; +/Users/andrew/Programming/rtk/src/playwright_cmd.rs:222: let mut cmd = package_manager_exec("playwright"); diff --git a/benchmarks/quality_samples/A4_rtk_grep.txt b/benchmarks/quality_samples/A4_rtk_grep.txt new file mode 100644 index 0000000..b89b053 --- /dev/null +++ b/benchmarks/quality_samples/A4_rtk_grep.txt @@ -0,0 +1,21 @@ +🔍 9 in 5F: + +📄 /Users/andrew/Programming/rtk/src/lint_cmd.rs (2): + 2: use crate::utils::{package_manager_exec, truncate}; + 39: let mut cmd = package_manager_exec(linter); + +📄 /.../src/playwright_cmd.rs (2): + 2: use crate::utils::{package_manager_exec, strip_ansi}; + 222: let mut cmd = package_manager_exec("playwright"); + +📄 /Users/andrew/Programming/rtk/src/prettier_cmd.rs (2): + 2: use crate::utils::package_manager_exec; + 8: let mut cmd = package_manager_exec("prettier"); + +📄 /Users/andrew/Programming/rtk/src/utils.rs (1): + 197: pub fn package_manager_exec(tool: &str) -> Command { + +📄 /Users/andrew/Programming/rtk/src/vitest_cmd.rs (2): + 10: use crate::utils::{package_manager_exec, strip_ansi}; + 225: let mut cmd = package_manager_exec("vitest"); + diff --git a/benchmarks/quality_samples/A4_rtk_rgai.txt b/benchmarks/quality_samples/A4_rtk_rgai.txt new file mode 100644 index 0000000..47fecfe --- /dev/null +++ b/benchmarks/quality_samples/A4_rtk_rgai.txt @@ -0,0 +1,44 @@ +🧠 5F for 'package_manager_exec' (scan 55F) + +📄 lint_cmd.rs [12.3] + 1: use crate::tracking; + 2: use crate::utils::{package_manager_exec, truncate}; + 3: use anyhow::{Context, Result}; + ~ package_manager_exec + + 39: let mut cmd = package_manager_exec(linter); + ~ package_manager_exec + +📄 playwright_cmd.rs [12.3] + 1: use crate::tracking; + 2: use crate::utils::{package_manager_exec, strip_ansi}; + 3: use anyhow::{Context, Result}; + ~ package_manager_exec + + 222: let mut cmd = package_manager_exec("playwright"); + ~ package_manager_exec + +📄 prettier_cmd.rs [12.3] + 1: use crate::tracking; + 2: use crate::utils::package_manager_exec; + 3: use anyhow::{Context, Result}; + ~ package_manager_exec + + 8: let mut cmd = package_manager_exec("prettier"); + ~ package_manager_exec + +📄 vitest_cmd.rs [12.3] + 9: use crate::tracking; + 10: use crate::utils::{package_manager_exec, strip_ansi}; + ~ package_manager_exec + + 225: let mut cmd = package_manager_exec("vitest"); + 226: cmd.arg("run"); // Force non-watch mode + ~ package_manager_exec + +📄 utils.rs [10.9] + 196: /// Returns a Command ready to have tool-specific args appended. + 197: pub fn package_manager_exec(tool: &str) -> Command { + 198: let tool_exists = Command::new("which") + ~ package_manager_exec + diff --git a/benchmarks/quality_samples/A5_grep.txt b/benchmarks/quality_samples/A5_grep.txt new file mode 100644 index 0000000..a08c298 --- /dev/null +++ b/benchmarks/quality_samples/A5_grep.txt @@ -0,0 +1,20 @@ +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:741:test utils::tests::test_strip_ansi_simple ... ok +/Users/andrew/Programming/rtk/src/vitest_cmd.rs:10:use crate::utils::{package_manager_exec, strip_ansi}; +/Users/andrew/Programming/rtk/src/vitest_cmd.rs:134: let clean_output = strip_ansi(output); +/Users/andrew/Programming/rtk/src/vitest_cmd.rs:324: fn test_strip_ansi() { +/Users/andrew/Programming/rtk/src/vitest_cmd.rs:326: let output = strip_ansi(input); +/Users/andrew/Programming/rtk/src/next_cmd.rs:2:use crate::utils::{strip_ansi, truncate}; +/Users/andrew/Programming/rtk/src/next_cmd.rs:80: let clean_output = strip_ansi(output); +/Users/andrew/Programming/rtk/src/utils.rs:43:/// use rtk::utils::strip_ansi; +/Users/andrew/Programming/rtk/src/utils.rs:45:/// assert_eq!(strip_ansi(colored), "Error"); +/Users/andrew/Programming/rtk/src/utils.rs:47:pub fn strip_ansi(text: &str) -> String { +/Users/andrew/Programming/rtk/src/utils.rs:259: fn test_strip_ansi_simple() { +/Users/andrew/Programming/rtk/src/utils.rs:261: assert_eq!(strip_ansi(input), "Error"); +/Users/andrew/Programming/rtk/src/utils.rs:265: fn test_strip_ansi_multiple() { +/Users/andrew/Programming/rtk/src/utils.rs:267: assert_eq!(strip_ansi(input), "Success"); +/Users/andrew/Programming/rtk/src/utils.rs:271: fn test_strip_ansi_no_codes() { +/Users/andrew/Programming/rtk/src/utils.rs:272: assert_eq!(strip_ansi("plain text"), "plain text"); +/Users/andrew/Programming/rtk/src/utils.rs:276: fn test_strip_ansi_complex() { +/Users/andrew/Programming/rtk/src/utils.rs:278: assert_eq!(strip_ansi(input), "Green normal Red"); +/Users/andrew/Programming/rtk/src/playwright_cmd.rs:2:use crate::utils::{package_manager_exec, strip_ansi}; +/Users/andrew/Programming/rtk/src/playwright_cmd.rs:150: let clean_output = strip_ansi(output); diff --git a/benchmarks/quality_samples/A5_head_n.txt b/benchmarks/quality_samples/A5_head_n.txt new file mode 100644 index 0000000..a08c298 --- /dev/null +++ b/benchmarks/quality_samples/A5_head_n.txt @@ -0,0 +1,20 @@ +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:741:test utils::tests::test_strip_ansi_simple ... ok +/Users/andrew/Programming/rtk/src/vitest_cmd.rs:10:use crate::utils::{package_manager_exec, strip_ansi}; +/Users/andrew/Programming/rtk/src/vitest_cmd.rs:134: let clean_output = strip_ansi(output); +/Users/andrew/Programming/rtk/src/vitest_cmd.rs:324: fn test_strip_ansi() { +/Users/andrew/Programming/rtk/src/vitest_cmd.rs:326: let output = strip_ansi(input); +/Users/andrew/Programming/rtk/src/next_cmd.rs:2:use crate::utils::{strip_ansi, truncate}; +/Users/andrew/Programming/rtk/src/next_cmd.rs:80: let clean_output = strip_ansi(output); +/Users/andrew/Programming/rtk/src/utils.rs:43:/// use rtk::utils::strip_ansi; +/Users/andrew/Programming/rtk/src/utils.rs:45:/// assert_eq!(strip_ansi(colored), "Error"); +/Users/andrew/Programming/rtk/src/utils.rs:47:pub fn strip_ansi(text: &str) -> String { +/Users/andrew/Programming/rtk/src/utils.rs:259: fn test_strip_ansi_simple() { +/Users/andrew/Programming/rtk/src/utils.rs:261: assert_eq!(strip_ansi(input), "Error"); +/Users/andrew/Programming/rtk/src/utils.rs:265: fn test_strip_ansi_multiple() { +/Users/andrew/Programming/rtk/src/utils.rs:267: assert_eq!(strip_ansi(input), "Success"); +/Users/andrew/Programming/rtk/src/utils.rs:271: fn test_strip_ansi_no_codes() { +/Users/andrew/Programming/rtk/src/utils.rs:272: assert_eq!(strip_ansi("plain text"), "plain text"); +/Users/andrew/Programming/rtk/src/utils.rs:276: fn test_strip_ansi_complex() { +/Users/andrew/Programming/rtk/src/utils.rs:278: assert_eq!(strip_ansi(input), "Green normal Red"); +/Users/andrew/Programming/rtk/src/playwright_cmd.rs:2:use crate::utils::{package_manager_exec, strip_ansi}; +/Users/andrew/Programming/rtk/src/playwright_cmd.rs:150: let clean_output = strip_ansi(output); diff --git a/benchmarks/quality_samples/A5_rtk_grep.txt b/benchmarks/quality_samples/A5_rtk_grep.txt new file mode 100644 index 0000000..70bc6d5 --- /dev/null +++ b/benchmarks/quality_samples/A5_rtk_grep.txt @@ -0,0 +1,33 @@ +🔍 20 in 5F: + +📄 /Users/andrew/Programming/rtk/src/cargo_cmd.rs (1): + 741: test utils::tests::test_strip_ansi_simple ... ok + +📄 /Users/andrew/Programming/rtk/src/next_cmd.rs (2): + 2: use crate::utils::{strip_ansi, truncate}; + 80: let clean_output = strip_ansi(output); + +📄 /.../src/playwright_cmd.rs (2): + 2: use crate::utils::{package_manager_exec, strip_ansi}; + 150: let clean_output = strip_ansi(output); + +📄 /Users/andrew/Programming/rtk/src/utils.rs (11): + 43: /// use rtk::utils::strip_ansi; + 45: /// assert_eq!(strip_ansi(colored), "Error"); + 47: pub fn strip_ansi(text: &str) -> String { + 259: fn test_strip_ansi_simple() { + 261: assert_eq!(strip_ansi(input), "Error"); + 265: fn test_strip_ansi_multiple() { + 267: assert_eq!(strip_ansi(input), "Success"); + 271: fn test_strip_ansi_no_codes() { + 272: assert_eq!(strip_ansi("plain text"), "plain text"); + 276: fn test_strip_ansi_complex() { + +1 + +📄 /Users/andrew/Programming/rtk/src/vitest_cmd.rs (4): + 10: use crate::utils::{package_manager_exec, strip_ansi}; + 134: let clean_output = strip_ansi(output); + 324: fn test_strip_ansi() { + 326: let output = strip_ansi(input); + +... +1 diff --git a/benchmarks/quality_samples/A5_rtk_rgai.txt b/benchmarks/quality_samples/A5_rtk_rgai.txt new file mode 100644 index 0000000..58d16a7 --- /dev/null +++ b/benchmarks/quality_samples/A5_rtk_rgai.txt @@ -0,0 +1,51 @@ +🧠 5F for 'strip_ansi' (scan 55F) + +📄 utils.rs [17.3] + 46: /// ``` + 47: pub fn strip_ansi(text: &str) -> String { + 48: lazy_static::lazy_static! { + ~ strip_ansi + + 258: #[test] + 259: fn test_strip_ansi_simple() { + 260: let input = "\x1b[31mError\x1b[0m"; + ~ strip_ansi + + +9 more lines + +📄 vitest_cmd.rs [15.3] + 323: #[test] + 324: fn test_strip_ansi() { + 325: let input = "\x1b[32m✓\x1b[0m test passed"; + ~ strip_ansi + + 9: use crate::tracking; + 10: use crate::utils::{package_manager_exec, strip_ansi}; + ~ strip_ansi + + +2 more lines + +📄 next_cmd.rs [12.3] + 1: use crate::tracking; + 2: use crate::utils::{strip_ansi, truncate}; + 3: use anyhow::{Context, Result}; + ~ strip_ansi + + 79: // Strip ANSI codes + 80: let clean_output = strip_ansi(output); + ~ strip_ansi + +📄 playwright_cmd.rs [12.3] + 1: use crate::tracking; + 2: use crate::utils::{package_manager_exec, strip_ansi}; + 3: use anyhow::{Context, Result}; + ~ strip_ansi + + 150: let clean_output = strip_ansi(output); + ~ strip_ansi + +📄 cargo_cmd.rs [8.4] + 740: test utils::tests::test_truncate_long_string ... ok + 741: test utils::tests::test_strip_ansi_simple ... ok + ~ strip_ansi + diff --git a/benchmarks/quality_samples/A6_grep.txt b/benchmarks/quality_samples/A6_grep.txt new file mode 100644 index 0000000..06de05a --- /dev/null +++ b/benchmarks/quality_samples/A6_grep.txt @@ -0,0 +1,2 @@ +/Users/andrew/Programming/rtk/src/tracking.rs:41:const HISTORY_DAYS: i64 = 90; +/Users/andrew/Programming/rtk/src/tracking.rs:315: let cutoff = Utc::now() - chrono::Duration::days(HISTORY_DAYS); diff --git a/benchmarks/quality_samples/A6_head_n.txt b/benchmarks/quality_samples/A6_head_n.txt new file mode 100644 index 0000000..06de05a --- /dev/null +++ b/benchmarks/quality_samples/A6_head_n.txt @@ -0,0 +1,2 @@ +/Users/andrew/Programming/rtk/src/tracking.rs:41:const HISTORY_DAYS: i64 = 90; +/Users/andrew/Programming/rtk/src/tracking.rs:315: let cutoff = Utc::now() - chrono::Duration::days(HISTORY_DAYS); diff --git a/benchmarks/quality_samples/A6_rtk_grep.txt b/benchmarks/quality_samples/A6_rtk_grep.txt new file mode 100644 index 0000000..d12c251 --- /dev/null +++ b/benchmarks/quality_samples/A6_rtk_grep.txt @@ -0,0 +1,6 @@ +🔍 2 in 1F: + +📄 /Users/andrew/Programming/rtk/src/tracking.rs (2): + 41: const HISTORY_DAYS: i64 = 90; + 315: let cutoff = Utc::now() - chrono::Duration::days(HISTORY_DAYS); + diff --git a/benchmarks/quality_samples/A6_rtk_rgai.txt b/benchmarks/quality_samples/A6_rtk_rgai.txt new file mode 100644 index 0000000..c86dbcd --- /dev/null +++ b/benchmarks/quality_samples/A6_rtk_rgai.txt @@ -0,0 +1,23 @@ +🧠 2F for 'HISTORY_DAYS' (scan 55F) + +📄 config.rs [16.5] + 17: pub enabled: bool, + 18: pub history_days: u32, + 19: #[serde(skip_serializing_if = "Option::is_none")] + ~ history_days, history_day + + 26: enabled: true, + 27: history_days: 90, + 28: database_path: None, + ~ history_days, history_day + +📄 tracking.rs [16.5] + 40: /// Number of days to retain tracking history before automatic cleanup. + 41: const HISTORY_DAYS: i64 = 90; + ~ history_days, history_day + + 314: fn cleanup_old(&self) -> Result<()> { + 315: let cutoff = Utc::now() - chrono::Duration::days(HISTORY_DAYS); + 316: self.conn.execute( + ~ history_days, history_day + diff --git a/benchmarks/quality_samples/B1_grep.txt b/benchmarks/quality_samples/B1_grep.txt new file mode 100644 index 0000000..b1d09df --- /dev/null +++ b/benchmarks/quality_samples/B1_grep.txt @@ -0,0 +1,27 @@ +/Users/andrew/Programming/rtk/src/pip_cmd.rs:14:pub fn run(args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/pytest_cmd.rs:14:pub fn run(args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/ls.rs:33:pub fn run(args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/local_llm.rs:9:pub fn run(file: &Path, _model: &str, _force_download: bool, verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/wget_cmd.rs:6:pub fn run(url: &str, args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/npm_cmd.rs:5:pub fn run(args: &[String], verbose: u8, skip_env: bool) -> Result<()> { +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:18:pub fn run(cmd: CargoCommand, args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/lint_cmd.rs:28:pub fn run(args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/curl_cmd.rs:7:pub fn run(args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:19:pub fn run(cmd: PrismaCommand, args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/golangci_cmd.rs:34:pub fn run(args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/git.rs:22:pub fn run(cmd: GitCommand, args: &[String], max_lines: Option, verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/deps.rs:8:pub fn run(path: &Path, verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:286:pub fn run(cmd: PnpmCommand, args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/tree.rs:43:pub fn run(args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/ruff_cmd.rs:31:pub fn run(args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/json_cmd.rs:9:pub fn run(file: &Path, max_depth: usize, verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/tsc_cmd.rs:8:pub fn run(args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/vitest_cmd.rs:216:pub fn run(cmd: VitestCommand, args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/diff_cmd.rs:8:pub fn run(file1: &Path, file2: &Path, verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/prettier_cmd.rs:5:pub fn run(args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/next_cmd.rs:7:pub fn run(args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/env_cmd.rs:7:pub fn run(filter: Option<&str>, show_all: bool, verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/container.rs:16:pub fn run(cmd: ContainerCmd, args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/gh_cmd.rs:15:pub fn run(subcommand: &str, args: &[String], verbose: u8, ultra_compact: bool) -> Result<()> { +/Users/andrew/Programming/rtk/src/playwright_cmd.rs:219:pub fn run(args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/summary.rs:8:pub fn run(command: &str, verbose: u8) -> Result<()> { diff --git a/benchmarks/quality_samples/B1_head_n.txt b/benchmarks/quality_samples/B1_head_n.txt new file mode 100644 index 0000000..b1d09df --- /dev/null +++ b/benchmarks/quality_samples/B1_head_n.txt @@ -0,0 +1,27 @@ +/Users/andrew/Programming/rtk/src/pip_cmd.rs:14:pub fn run(args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/pytest_cmd.rs:14:pub fn run(args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/ls.rs:33:pub fn run(args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/local_llm.rs:9:pub fn run(file: &Path, _model: &str, _force_download: bool, verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/wget_cmd.rs:6:pub fn run(url: &str, args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/npm_cmd.rs:5:pub fn run(args: &[String], verbose: u8, skip_env: bool) -> Result<()> { +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:18:pub fn run(cmd: CargoCommand, args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/lint_cmd.rs:28:pub fn run(args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/curl_cmd.rs:7:pub fn run(args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:19:pub fn run(cmd: PrismaCommand, args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/golangci_cmd.rs:34:pub fn run(args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/git.rs:22:pub fn run(cmd: GitCommand, args: &[String], max_lines: Option, verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/deps.rs:8:pub fn run(path: &Path, verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:286:pub fn run(cmd: PnpmCommand, args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/tree.rs:43:pub fn run(args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/ruff_cmd.rs:31:pub fn run(args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/json_cmd.rs:9:pub fn run(file: &Path, max_depth: usize, verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/tsc_cmd.rs:8:pub fn run(args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/vitest_cmd.rs:216:pub fn run(cmd: VitestCommand, args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/diff_cmd.rs:8:pub fn run(file1: &Path, file2: &Path, verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/prettier_cmd.rs:5:pub fn run(args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/next_cmd.rs:7:pub fn run(args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/env_cmd.rs:7:pub fn run(filter: Option<&str>, show_all: bool, verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/container.rs:16:pub fn run(cmd: ContainerCmd, args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/gh_cmd.rs:15:pub fn run(subcommand: &str, args: &[String], verbose: u8, ultra_compact: bool) -> Result<()> { +/Users/andrew/Programming/rtk/src/playwright_cmd.rs:219:pub fn run(args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/summary.rs:8:pub fn run(command: &str, verbose: u8) -> Result<()> { diff --git a/benchmarks/quality_samples/B1_rtk_grep.txt b/benchmarks/quality_samples/B1_rtk_grep.txt new file mode 100644 index 0000000..1f44afc --- /dev/null +++ b/benchmarks/quality_samples/B1_rtk_grep.txt @@ -0,0 +1,83 @@ +🔍 27 in 27F: + +📄 /Users/andrew/Programming/rtk/src/cargo_cmd.rs (1): + 18: pub fn run(cmd: CargoCommand, args: &[String], verbose: u8) -> Result<()> { + +📄 /Users/andrew/Programming/rtk/src/container.rs (1): + 16: pub fn run(cmd: ContainerCmd, args: &[String], verbose: u8) -> Result<()> { + +📄 /Users/andrew/Programming/rtk/src/curl_cmd.rs (1): + 7: pub fn run(args: &[String], verbose: u8) -> Result<()> { + +📄 /Users/andrew/Programming/rtk/src/deps.rs (1): + 8: pub fn run(path: &Path, verbose: u8) -> Result<()> { + +📄 /Users/andrew/Programming/rtk/src/diff_cmd.rs (1): + 8: pub fn run(file1: &Path, file2: &Path, verbose: u8) -> Result<()> { + +📄 /Users/andrew/Programming/rtk/src/env_cmd.rs (1): + 7: pub fn run(filter: Option<&str>, show_all: bool, verbose: u8) -> Result<()> { + +📄 /Users/andrew/Programming/rtk/src/gh_cmd.rs (1): + 15: pub fn run(subcommand: &str, args: &[String], verbose: u8, ultra_compact: boo... + +📄 /Users/andrew/Programming/rtk/src/git.rs (1): + 22: pub fn run(cmd: GitCommand, args: &[String], max_lines: Option, verbos... + +📄 /Users/andrew/Programming/rtk/src/golangci_cmd.rs (1): + 34: pub fn run(args: &[String], verbose: u8) -> Result<()> { + +📄 /Users/andrew/Programming/rtk/src/json_cmd.rs (1): + 9: pub fn run(file: &Path, max_depth: usize, verbose: u8) -> Result<()> { + +📄 /Users/andrew/Programming/rtk/src/lint_cmd.rs (1): + 28: pub fn run(args: &[String], verbose: u8) -> Result<()> { + +📄 /Users/andrew/Programming/rtk/src/local_llm.rs (1): + 9: pub fn run(file: &Path, _model: &str, _force_download: bool, verbose: u8) -> ... + +📄 /Users/andrew/Programming/rtk/src/ls.rs (1): + 33: pub fn run(args: &[String], verbose: u8) -> Result<()> { + +📄 /Users/andrew/Programming/rtk/src/next_cmd.rs (1): + 7: pub fn run(args: &[String], verbose: u8) -> Result<()> { + +📄 /Users/andrew/Programming/rtk/src/npm_cmd.rs (1): + 5: pub fn run(args: &[String], verbose: u8, skip_env: bool) -> Result<()> { + +📄 /Users/andrew/Programming/rtk/src/pip_cmd.rs (1): + 14: pub fn run(args: &[String], verbose: u8) -> Result<()> { + +📄 /.../src/playwright_cmd.rs (1): + 219: pub fn run(args: &[String], verbose: u8) -> Result<()> { + +📄 /Users/andrew/Programming/rtk/src/pnpm_cmd.rs (1): + 286: pub fn run(cmd: PnpmCommand, args: &[String], verbose: u8) -> Result<()> { + +📄 /Users/andrew/Programming/rtk/src/prettier_cmd.rs (1): + 5: pub fn run(args: &[String], verbose: u8) -> Result<()> { + +📄 /Users/andrew/Programming/rtk/src/prisma_cmd.rs (1): + 19: pub fn run(cmd: PrismaCommand, args: &[String], verbose: u8) -> Result<()> { + +📄 /Users/andrew/Programming/rtk/src/pytest_cmd.rs (1): + 14: pub fn run(args: &[String], verbose: u8) -> Result<()> { + +📄 /Users/andrew/Programming/rtk/src/ruff_cmd.rs (1): + 31: pub fn run(args: &[String], verbose: u8) -> Result<()> { + +📄 /Users/andrew/Programming/rtk/src/summary.rs (1): + 8: pub fn run(command: &str, verbose: u8) -> Result<()> { + +📄 /Users/andrew/Programming/rtk/src/tree.rs (1): + 43: pub fn run(args: &[String], verbose: u8) -> Result<()> { + +📄 /Users/andrew/Programming/rtk/src/tsc_cmd.rs (1): + 8: pub fn run(args: &[String], verbose: u8) -> Result<()> { + +📄 /Users/andrew/Programming/rtk/src/vitest_cmd.rs (1): + 216: pub fn run(cmd: VitestCommand, args: &[String], verbose: u8) -> Result<()> { + +📄 /Users/andrew/Programming/rtk/src/wget_cmd.rs (1): + 6: pub fn run(url: &str, args: &[String], verbose: u8) -> Result<()> { + diff --git a/benchmarks/quality_samples/B1_rtk_rgai.txt b/benchmarks/quality_samples/B1_rtk_rgai.txt new file mode 100644 index 0000000..7f65693 --- /dev/null +++ b/benchmarks/quality_samples/B1_rtk_rgai.txt @@ -0,0 +1,99 @@ +🧠 54F for 'fn run\(.*verbose: u8' (scan 55F) + +📄 gh_cmd.rs [18.6] + 14: /// Run a gh command with token-optimized output + 15: pub fn run(subcommand: &str, args: &[String], verbose: u8, ultra_compact: bool) -> Result<()> { + 16: match subcommand { + ~ fn, run, verbose, u8 + + 29: fn run_pr(args: &[String], verbose: u8, ultra_compact: bool) -> Result<()> { + 30: if args.is_empty() { + ~ fn, run, verbose, u8 + + +106 more lines + +📄 git.rs [18.5] + 22: pub fn run(cmd: GitCommand, args: &[String], max_lines: Option, verbose: u8) -> Result<()> { + 23: match cmd { + ~ fn, run, verbose, u8 + + 39: fn run_diff(args: &[String], max_lines: Option, verbose: u8) -> Result<()> { + 40: let timer = tracking::TimedExecution::start(); + ~ fn, run, verbose, u8 + + +94 more lines + +📄 cargo_cmd.rs [18.5] + 18: pub fn run(cmd: CargoCommand, args: &[String], verbose: u8) -> Result<()> { + 19: match cmd { + ~ fn, run, verbose, u8 + + 28: /// Generic cargo command runner with filtering + 29: fn run_cargo_filtered(subcommand: &str, args: &[String], verbose: u8, filter_fn: F) -> Result<()> + 30: where + ~ fn, run, verbose, u8 + + +91 more lines + +📄 init.rs [18.4] + 651: #[cfg(not(unix))] + 652: fn run_default_mode(_global: bool, _patch_mode: PatchMode, _verbose: u8) -> Result<()> { + 653: eprintln!("⚠️ Hook-based mode requires Unix (macOS/Linux)."); + ~ fn, run, verbose, u8 + + 659: #[cfg(unix)] + 660: fn run_default_mode(global: bool, patch_mode: PatchMode, verbose: u8) -> Result<()> { + 661: if !global { + ~ fn, run, verbose, u8 + + +87 more lines + +📄 runner.rs [17.6] + 6: /// Run a command and filter output to show only errors/warnings + 7: pub fn run_err(command: &str, verbose: u8) -> Result<()> { + 8: let timer = tracking::TimedExecution::start(); + ~ fn, run, verbose, u8 + + 57: /// Run tests and show only failures + 58: pub fn run_test(command: &str, verbose: u8) -> Result<()> { + 59: let timer = tracking::TimedExecution::start(); + ~ fn, run, verbose, u8 + + +9 more lines + +📄 go_cmd.rs [17.6] + 34: pub fn run_test(args: &[String], verbose: u8) -> Result<()> { + 35: let timer = tracking::TimedExecution::start(); + ~ fn, run, verbose, u8 + + 85: pub fn run_build(args: &[String], verbose: u8) -> Result<()> { + 86: let timer = tracking::TimedExecution::start(); + ~ fn, run, verbose, u8 + + +35 more lines + +📄 pnpm_cmd.rs [17.5] + 286: pub fn run(cmd: PnpmCommand, args: &[String], verbose: u8) -> Result<()> { + 287: match cmd { + ~ fn, run, verbose, u8 + + 294: fn run_list(depth: usize, args: &[String], verbose: u8) -> Result<()> { + 295: let timer = tracking::TimedExecution::start(); + ~ fn, run, verbose, u8 + + +33 more lines + +📄 diff_cmd.rs [17.5] + 7: /// Ultra-condensed diff - only changed lines, no context + 8: pub fn run(file1: &Path, file2: &Path, verbose: u8) -> Result<()> { + 9: let timer = tracking::TimedExecution::start(); + ~ fn, run, verbose, u8 + + 68: /// Run diff from stdin (piped command output) + 69: pub fn run_stdin(_verbose: u8) -> Result<()> { + 70: use std::io::{self, Read}; + ~ fn, run, verbose, u8 + + +32 more lines + +... +46F diff --git a/benchmarks/quality_samples/B2_grep.txt b/benchmarks/quality_samples/B2_grep.txt new file mode 100644 index 0000000..6275dc2 --- /dev/null +++ b/benchmarks/quality_samples/B2_grep.txt @@ -0,0 +1,116 @@ +/Users/andrew/Programming/rtk/src/pip_cmd.rs:43: timer.track( +/Users/andrew/Programming/rtk/src/pytest_cmd.rs:63: timer.track( +/Users/andrew/Programming/rtk/src/ls.rs:113: timer.track( +/Users/andrew/Programming/rtk/src/wget_cmd.rs:42: timer.track(&format!("wget {}", url), "rtk wget", &raw_output, &msg); +/Users/andrew/Programming/rtk/src/wget_cmd.rs:47: timer.track(&format!("wget {}", url), "rtk wget", &raw_output, &msg); +/Users/andrew/Programming/rtk/src/wget_cmd.rs:98: timer.track( +/Users/andrew/Programming/rtk/src/wget_cmd.rs:109: timer.track(&format!("wget -O - {}", url), "rtk wget -o", &stderr, &msg); +/Users/andrew/Programming/rtk/src/npm_cmd.rs:31: timer.track( +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:55: timer.track( +/Users/andrew/Programming/rtk/src/go_cmd.rs:70: timer.track( +/Users/andrew/Programming/rtk/src/go_cmd.rs:113: timer.track( +/Users/andrew/Programming/rtk/src/go_cmd.rs:156: timer.track( +/Users/andrew/Programming/rtk/src/go_cmd.rs:201: timer.track( +/Users/andrew/Programming/rtk/src/lint_cmd.rs:89: timer.track( +/Users/andrew/Programming/rtk/src/curl_cmd.rs:40: timer.track( +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:74: timer.track("prisma generate", "rtk prisma generate", &raw, &filtered); +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:130: timer.track(cmd_name, &format!("rtk {}", cmd_name), &raw, &filtered); +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:163: timer.track("prisma db push", "rtk prisma db push", &raw, &filtered); +/Users/andrew/Programming/rtk/src/find_cmd.rs:101: timer.track( +/Users/andrew/Programming/rtk/src/find_cmd.rs:195: timer.track( +/Users/andrew/Programming/rtk/src/golangci_cmd.rs:75: timer.track( +/Users/andrew/Programming/rtk/src/git.rs:69: timer.track( +/Users/andrew/Programming/rtk/src/git.rs:116: timer.track( +/Users/andrew/Programming/rtk/src/git.rs:153: timer.track( +/Users/andrew/Programming/rtk/src/git.rs:222: timer.track( +/Users/andrew/Programming/rtk/src/git.rs:364: timer.track( +/Users/andrew/Programming/rtk/src/git.rs:548: timer.track( +/Users/andrew/Programming/rtk/src/git.rs:577: timer.track("git status", "rtk git status", &raw_output, &formatted); +/Users/andrew/Programming/rtk/src/git.rs:631: timer.track( +/Users/andrew/Programming/rtk/src/git.rs:689: timer.track( +/Users/andrew/Programming/rtk/src/git.rs:698: timer.track( +/Users/andrew/Programming/rtk/src/git.rs:760: timer.track( +/Users/andrew/Programming/rtk/src/git.rs:845: timer.track( +/Users/andrew/Programming/rtk/src/git.rs:894: timer.track( +/Users/andrew/Programming/rtk/src/git.rs:928: timer.track( +/Users/andrew/Programming/rtk/src/git.rs:1031: timer.track("git fetch", "rtk git fetch", &raw, &msg); +/Users/andrew/Programming/rtk/src/git.rs:1055: timer.track("git stash list", "rtk git stash list", &raw, msg); +/Users/andrew/Programming/rtk/src/git.rs:1061: timer.track("git stash list", "rtk git stash list", &raw, &filtered); +/Users/andrew/Programming/rtk/src/git.rs:1083: timer.track("git stash show", "rtk git stash show", &raw, &filtered); +/Users/andrew/Programming/rtk/src/git.rs:1109: timer.track( +/Users/andrew/Programming/rtk/src/git.rs:1146: timer.track("git stash", "rtk git stash", &combined, &msg); +/Users/andrew/Programming/rtk/src/git.rs:1203: timer.track( +/Users/andrew/Programming/rtk/src/git.rs:1232: timer.track("git worktree list", "rtk git worktree", &raw, &filtered); +/Users/andrew/Programming/rtk/src/runner.rs:53: timer.track(command, "rtk run-err", &raw, &rtk); +/Users/andrew/Programming/rtk/src/runner.rs:86: timer.track(command, "rtk run-test", &raw, &summary); +/Users/andrew/Programming/rtk/src/deps.rs:70: timer.track("cat */deps", "rtk deps", &raw, &rtk); +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:340: timer.track( +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:396: timer.track("pnpm outdated", "rtk pnpm outdated", &combined, &filtered); +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:442: timer.track( +/Users/andrew/Programming/rtk/src/tree.rs:100: timer.track("tree", "rtk tree", &raw, &filtered); +/Users/andrew/Programming/rtk/src/log_cmd.rs:20: timer.track( +/Users/andrew/Programming/rtk/src/log_cmd.rs:43: timer.track("log (stdin)", "rtk log (stdin)", &content, &result); +/Users/andrew/Programming/rtk/src/ruff_cmd.rs:99: timer.track( +/Users/andrew/Programming/rtk/src/grep_cmd.rs:46: timer.track( +/Users/andrew/Programming/rtk/src/grep_cmd.rs:110: timer.track( +/Users/andrew/Programming/rtk/src/json_cmd.rs:21: timer.track( +/Users/andrew/Programming/rtk/src/json_cmd.rs:46: timer.track("cat - (stdin)", "rtk json -", &content, &schema); +/Users/andrew/Programming/rtk/src/read.rs:64: timer.track( +/Users/andrew/Programming/rtk/src/read.rs:131: timer.track("cat - (stdin)", "rtk read -", &content, &rtk_output); +/Users/andrew/Programming/rtk/src/tsc_cmd.rs:46: timer.track( +/Users/andrew/Programming/rtk/src/vitest_cmd.rs:265: timer.track("vitest run", "rtk vitest run", &combined, &filtered); +/Users/andrew/Programming/rtk/src/tracking.rs:22://! timer.track("ls -la", "rtk ls", input, output); +/Users/andrew/Programming/rtk/src/tracking.rs:736:/// timer.track("ls -la", "rtk ls", &input, &output); +/Users/andrew/Programming/rtk/src/tracking.rs:757: /// timer.track("cmd", "rtk cmd", "input", "output"); +/Users/andrew/Programming/rtk/src/tracking.rs:787: /// timer.track("ls -la", "rtk ls", input, output); +/Users/andrew/Programming/rtk/src/tracking.rs:878:/// timer.track("ls -la", "rtk ls", "input", "output"); +/Users/andrew/Programming/rtk/src/tracking.rs:988: timer.track("test cmd", "rtk test", "raw input data", "filtered"); +/Users/andrew/Programming/rtk/src/main.rs:1430: timer.track( +/Users/andrew/Programming/rtk/src/diff_cmd.rs:27: timer.track( +/Users/andrew/Programming/rtk/src/diff_cmd.rs:59: timer.track( +/Users/andrew/Programming/rtk/src/diff_cmd.rs:80: timer.track("diff (stdin)", "rtk diff (stdin)", &input, &condensed); +/Users/andrew/Programming/rtk/src/prettier_cmd.rs:31: timer.track( +/Users/andrew/Programming/rtk/src/next_cmd.rs:47: timer.track("next build", "rtk next build", &raw, &filtered); +/Users/andrew/Programming/rtk/src/env_cmd.rs:126: timer.track("env", "rtk env", &raw, &rtk); +/Users/andrew/Programming/rtk/src/container.rs:51: timer.track("docker ps", "rtk docker ps", &raw, &rtk); +/Users/andrew/Programming/rtk/src/container.rs:80: timer.track("docker ps", "rtk docker ps", &raw, &rtk); +/Users/andrew/Programming/rtk/src/container.rs:105: timer.track("docker images", "rtk docker images", &raw, &rtk); +/Users/andrew/Programming/rtk/src/container.rs:150: timer.track("docker images", "rtk docker images", &raw, &rtk); +/Users/andrew/Programming/rtk/src/container.rs:175: timer.track( +/Users/andrew/Programming/rtk/src/container.rs:202: timer.track("kubectl get pods", "rtk kubectl pods", &raw, &rtk); +/Users/andrew/Programming/rtk/src/container.rs:211: timer.track("kubectl get pods", "rtk kubectl pods", &raw, &rtk); +/Users/andrew/Programming/rtk/src/container.rs:281: timer.track("kubectl get pods", "rtk kubectl pods", &raw, &rtk); +/Users/andrew/Programming/rtk/src/container.rs:303: timer.track("kubectl get svc", "rtk kubectl svc", &raw, &rtk); +/Users/andrew/Programming/rtk/src/container.rs:312: timer.track("kubectl get svc", "rtk kubectl svc", &raw, &rtk); +/Users/andrew/Programming/rtk/src/container.rs:355: timer.track("kubectl get svc", "rtk kubectl svc", &raw, &rtk); +/Users/andrew/Programming/rtk/src/container.rs:379: timer.track( +/Users/andrew/Programming/rtk/src/gh_cmd.rs:69: timer.track("gh pr list", "rtk gh pr list", &stderr, &stderr); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:128: timer.track("gh pr list", "rtk gh pr list", &raw, &filtered); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:155: timer.track( +/Users/andrew/Programming/rtk/src/gh_cmd.rs:296: timer.track( +/Users/andrew/Programming/rtk/src/gh_cmd.rs:322: timer.track( +/Users/andrew/Programming/rtk/src/gh_cmd.rs:382: timer.track( +/Users/andrew/Programming/rtk/src/gh_cmd.rs:407: timer.track("gh pr status", "rtk gh pr status", &stderr, &stderr); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:431: timer.track("gh pr status", "rtk gh pr status", &raw, &filtered); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:462: timer.track("gh issue list", "rtk gh issue list", &stderr, &stderr); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:510: timer.track("gh issue list", "rtk gh issue list", &raw, &filtered); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:537: timer.track( +/Users/andrew/Programming/rtk/src/gh_cmd.rs:591: timer.track( +/Users/andrew/Programming/rtk/src/gh_cmd.rs:633: timer.track("gh run list", "rtk gh run list", &stderr, &stderr); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:691: timer.track("gh run list", "rtk gh run list", &raw, &filtered); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:712: timer.track( +/Users/andrew/Programming/rtk/src/gh_cmd.rs:754: timer.track( +/Users/andrew/Programming/rtk/src/gh_cmd.rs:794: timer.track("gh repo view", "rtk gh repo view", &stderr, &stderr); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:840: timer.track("gh repo view", "rtk gh repo view", &raw, &filtered); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:858: timer.track("gh pr create", "rtk gh pr create", &stderr, &stderr); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:878: timer.track("gh pr create", "rtk gh pr create", &stdout, &filtered); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:896: timer.track("gh pr merge", "rtk gh pr merge", &stderr, &stderr); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:924: timer.track("gh pr merge", "rtk gh pr merge", &raw, &filtered); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:942: timer.track("gh pr diff", "rtk gh pr diff", &stderr, &stderr); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:957: timer.track("gh pr diff", "rtk gh pr diff", &raw, &filtered); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:978: timer.track( +/Users/andrew/Programming/rtk/src/gh_cmd.rs:1005: timer.track( +/Users/andrew/Programming/rtk/src/gh_cmd.rs:1028: timer.track("gh api", "rtk gh api", &stderr, &stderr); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:1054: timer.track("gh api", "rtk gh api", &raw, &filtered); +/Users/andrew/Programming/rtk/src/playwright_cmd.rs:268: timer.track( +/Users/andrew/Programming/rtk/src/summary.rs:36: timer.track(command, "rtk summary", &raw, &summary); diff --git a/benchmarks/quality_samples/B2_head_n.txt b/benchmarks/quality_samples/B2_head_n.txt new file mode 100644 index 0000000..e4bde4f --- /dev/null +++ b/benchmarks/quality_samples/B2_head_n.txt @@ -0,0 +1,100 @@ +/Users/andrew/Programming/rtk/src/pip_cmd.rs:43: timer.track( +/Users/andrew/Programming/rtk/src/pytest_cmd.rs:63: timer.track( +/Users/andrew/Programming/rtk/src/ls.rs:113: timer.track( +/Users/andrew/Programming/rtk/src/wget_cmd.rs:42: timer.track(&format!("wget {}", url), "rtk wget", &raw_output, &msg); +/Users/andrew/Programming/rtk/src/wget_cmd.rs:47: timer.track(&format!("wget {}", url), "rtk wget", &raw_output, &msg); +/Users/andrew/Programming/rtk/src/wget_cmd.rs:98: timer.track( +/Users/andrew/Programming/rtk/src/wget_cmd.rs:109: timer.track(&format!("wget -O - {}", url), "rtk wget -o", &stderr, &msg); +/Users/andrew/Programming/rtk/src/npm_cmd.rs:31: timer.track( +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:55: timer.track( +/Users/andrew/Programming/rtk/src/go_cmd.rs:70: timer.track( +/Users/andrew/Programming/rtk/src/go_cmd.rs:113: timer.track( +/Users/andrew/Programming/rtk/src/go_cmd.rs:156: timer.track( +/Users/andrew/Programming/rtk/src/go_cmd.rs:201: timer.track( +/Users/andrew/Programming/rtk/src/lint_cmd.rs:89: timer.track( +/Users/andrew/Programming/rtk/src/curl_cmd.rs:40: timer.track( +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:74: timer.track("prisma generate", "rtk prisma generate", &raw, &filtered); +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:130: timer.track(cmd_name, &format!("rtk {}", cmd_name), &raw, &filtered); +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:163: timer.track("prisma db push", "rtk prisma db push", &raw, &filtered); +/Users/andrew/Programming/rtk/src/find_cmd.rs:101: timer.track( +/Users/andrew/Programming/rtk/src/find_cmd.rs:195: timer.track( +/Users/andrew/Programming/rtk/src/golangci_cmd.rs:75: timer.track( +/Users/andrew/Programming/rtk/src/git.rs:69: timer.track( +/Users/andrew/Programming/rtk/src/git.rs:116: timer.track( +/Users/andrew/Programming/rtk/src/git.rs:153: timer.track( +/Users/andrew/Programming/rtk/src/git.rs:222: timer.track( +/Users/andrew/Programming/rtk/src/git.rs:364: timer.track( +/Users/andrew/Programming/rtk/src/git.rs:548: timer.track( +/Users/andrew/Programming/rtk/src/git.rs:577: timer.track("git status", "rtk git status", &raw_output, &formatted); +/Users/andrew/Programming/rtk/src/git.rs:631: timer.track( +/Users/andrew/Programming/rtk/src/git.rs:689: timer.track( +/Users/andrew/Programming/rtk/src/git.rs:698: timer.track( +/Users/andrew/Programming/rtk/src/git.rs:760: timer.track( +/Users/andrew/Programming/rtk/src/git.rs:845: timer.track( +/Users/andrew/Programming/rtk/src/git.rs:894: timer.track( +/Users/andrew/Programming/rtk/src/git.rs:928: timer.track( +/Users/andrew/Programming/rtk/src/git.rs:1031: timer.track("git fetch", "rtk git fetch", &raw, &msg); +/Users/andrew/Programming/rtk/src/git.rs:1055: timer.track("git stash list", "rtk git stash list", &raw, msg); +/Users/andrew/Programming/rtk/src/git.rs:1061: timer.track("git stash list", "rtk git stash list", &raw, &filtered); +/Users/andrew/Programming/rtk/src/git.rs:1083: timer.track("git stash show", "rtk git stash show", &raw, &filtered); +/Users/andrew/Programming/rtk/src/git.rs:1109: timer.track( +/Users/andrew/Programming/rtk/src/git.rs:1146: timer.track("git stash", "rtk git stash", &combined, &msg); +/Users/andrew/Programming/rtk/src/git.rs:1203: timer.track( +/Users/andrew/Programming/rtk/src/git.rs:1232: timer.track("git worktree list", "rtk git worktree", &raw, &filtered); +/Users/andrew/Programming/rtk/src/runner.rs:53: timer.track(command, "rtk run-err", &raw, &rtk); +/Users/andrew/Programming/rtk/src/runner.rs:86: timer.track(command, "rtk run-test", &raw, &summary); +/Users/andrew/Programming/rtk/src/deps.rs:70: timer.track("cat */deps", "rtk deps", &raw, &rtk); +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:340: timer.track( +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:396: timer.track("pnpm outdated", "rtk pnpm outdated", &combined, &filtered); +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:442: timer.track( +/Users/andrew/Programming/rtk/src/tree.rs:100: timer.track("tree", "rtk tree", &raw, &filtered); +/Users/andrew/Programming/rtk/src/log_cmd.rs:20: timer.track( +/Users/andrew/Programming/rtk/src/log_cmd.rs:43: timer.track("log (stdin)", "rtk log (stdin)", &content, &result); +/Users/andrew/Programming/rtk/src/ruff_cmd.rs:99: timer.track( +/Users/andrew/Programming/rtk/src/grep_cmd.rs:46: timer.track( +/Users/andrew/Programming/rtk/src/grep_cmd.rs:110: timer.track( +/Users/andrew/Programming/rtk/src/json_cmd.rs:21: timer.track( +/Users/andrew/Programming/rtk/src/json_cmd.rs:46: timer.track("cat - (stdin)", "rtk json -", &content, &schema); +/Users/andrew/Programming/rtk/src/read.rs:64: timer.track( +/Users/andrew/Programming/rtk/src/read.rs:131: timer.track("cat - (stdin)", "rtk read -", &content, &rtk_output); +/Users/andrew/Programming/rtk/src/tsc_cmd.rs:46: timer.track( +/Users/andrew/Programming/rtk/src/vitest_cmd.rs:265: timer.track("vitest run", "rtk vitest run", &combined, &filtered); +/Users/andrew/Programming/rtk/src/tracking.rs:22://! timer.track("ls -la", "rtk ls", input, output); +/Users/andrew/Programming/rtk/src/tracking.rs:736:/// timer.track("ls -la", "rtk ls", &input, &output); +/Users/andrew/Programming/rtk/src/tracking.rs:757: /// timer.track("cmd", "rtk cmd", "input", "output"); +/Users/andrew/Programming/rtk/src/tracking.rs:787: /// timer.track("ls -la", "rtk ls", input, output); +/Users/andrew/Programming/rtk/src/tracking.rs:878:/// timer.track("ls -la", "rtk ls", "input", "output"); +/Users/andrew/Programming/rtk/src/tracking.rs:988: timer.track("test cmd", "rtk test", "raw input data", "filtered"); +/Users/andrew/Programming/rtk/src/main.rs:1430: timer.track( +/Users/andrew/Programming/rtk/src/diff_cmd.rs:27: timer.track( +/Users/andrew/Programming/rtk/src/diff_cmd.rs:59: timer.track( +/Users/andrew/Programming/rtk/src/diff_cmd.rs:80: timer.track("diff (stdin)", "rtk diff (stdin)", &input, &condensed); +/Users/andrew/Programming/rtk/src/prettier_cmd.rs:31: timer.track( +/Users/andrew/Programming/rtk/src/next_cmd.rs:47: timer.track("next build", "rtk next build", &raw, &filtered); +/Users/andrew/Programming/rtk/src/env_cmd.rs:126: timer.track("env", "rtk env", &raw, &rtk); +/Users/andrew/Programming/rtk/src/container.rs:51: timer.track("docker ps", "rtk docker ps", &raw, &rtk); +/Users/andrew/Programming/rtk/src/container.rs:80: timer.track("docker ps", "rtk docker ps", &raw, &rtk); +/Users/andrew/Programming/rtk/src/container.rs:105: timer.track("docker images", "rtk docker images", &raw, &rtk); +/Users/andrew/Programming/rtk/src/container.rs:150: timer.track("docker images", "rtk docker images", &raw, &rtk); +/Users/andrew/Programming/rtk/src/container.rs:175: timer.track( +/Users/andrew/Programming/rtk/src/container.rs:202: timer.track("kubectl get pods", "rtk kubectl pods", &raw, &rtk); +/Users/andrew/Programming/rtk/src/container.rs:211: timer.track("kubectl get pods", "rtk kubectl pods", &raw, &rtk); +/Users/andrew/Programming/rtk/src/container.rs:281: timer.track("kubectl get pods", "rtk kubectl pods", &raw, &rtk); +/Users/andrew/Programming/rtk/src/container.rs:303: timer.track("kubectl get svc", "rtk kubectl svc", &raw, &rtk); +/Users/andrew/Programming/rtk/src/container.rs:312: timer.track("kubectl get svc", "rtk kubectl svc", &raw, &rtk); +/Users/andrew/Programming/rtk/src/container.rs:355: timer.track("kubectl get svc", "rtk kubectl svc", &raw, &rtk); +/Users/andrew/Programming/rtk/src/container.rs:379: timer.track( +/Users/andrew/Programming/rtk/src/gh_cmd.rs:69: timer.track("gh pr list", "rtk gh pr list", &stderr, &stderr); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:128: timer.track("gh pr list", "rtk gh pr list", &raw, &filtered); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:155: timer.track( +/Users/andrew/Programming/rtk/src/gh_cmd.rs:296: timer.track( +/Users/andrew/Programming/rtk/src/gh_cmd.rs:322: timer.track( +/Users/andrew/Programming/rtk/src/gh_cmd.rs:382: timer.track( +/Users/andrew/Programming/rtk/src/gh_cmd.rs:407: timer.track("gh pr status", "rtk gh pr status", &stderr, &stderr); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:431: timer.track("gh pr status", "rtk gh pr status", &raw, &filtered); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:462: timer.track("gh issue list", "rtk gh issue list", &stderr, &stderr); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:510: timer.track("gh issue list", "rtk gh issue list", &raw, &filtered); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:537: timer.track( +/Users/andrew/Programming/rtk/src/gh_cmd.rs:591: timer.track( +/Users/andrew/Programming/rtk/src/gh_cmd.rs:633: timer.track("gh run list", "rtk gh run list", &stderr, &stderr); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:691: timer.track("gh run list", "rtk gh run list", &raw, &filtered); diff --git a/benchmarks/quality_samples/B2_rtk_grep.txt b/benchmarks/quality_samples/B2_rtk_grep.txt new file mode 100644 index 0000000..023d498 --- /dev/null +++ b/benchmarks/quality_samples/B2_rtk_grep.txt @@ -0,0 +1,158 @@ +🔍 116 in 34F: + +📄 /Users/andrew/Programming/rtk/src/cargo_cmd.rs (1): + 55: timer.track( + +📄 /Users/andrew/Programming/rtk/src/container.rs (12): + 51: timer.track("docker ps", "rtk docker ps", &raw, &rtk); + 80: timer.track("docker ps", "rtk docker ps", &raw, &rtk); + 105: timer.track("docker images", "rtk docker images", &raw, &rtk); + 150: timer.track("docker images", "rtk docker images", &raw, &rtk); + 175: timer.track( + 202: timer.track("kubectl get pods", "rtk kubectl pods", &raw, &rtk); + 211: timer.track("kubectl get pods", "rtk kubectl pods", &raw, &rtk); + 281: timer.track("kubectl get pods", "rtk kubectl pods", &raw, &rtk); + 303: timer.track("kubectl get svc", "rtk kubectl svc", &raw, &rtk); + 312: timer.track("kubectl get svc", "rtk kubectl svc", &raw, &rtk); + +2 + +📄 /Users/andrew/Programming/rtk/src/curl_cmd.rs (1): + 40: timer.track( + +📄 /Users/andrew/Programming/rtk/src/deps.rs (1): + 70: timer.track("cat */deps", "rtk deps", &raw, &rtk); + +📄 /Users/andrew/Programming/rtk/src/diff_cmd.rs (3): + 27: timer.track( + 59: timer.track( + 80: timer.track("diff (stdin)", "rtk diff (stdin)", &input, &condensed); + +📄 /Users/andrew/Programming/rtk/src/env_cmd.rs (1): + 126: timer.track("env", "rtk env", &raw, &rtk); + +📄 /Users/andrew/Programming/rtk/src/find_cmd.rs (2): + 101: timer.track( + 195: timer.track( + +📄 /Users/andrew/Programming/rtk/src/gh_cmd.rs (28): + 69: timer.track("gh pr list", "rtk gh pr list", &stderr, &stderr); + 128: timer.track("gh pr list", "rtk gh pr list", &raw, &filtered); + 155: timer.track( + 296: timer.track( + 322: timer.track( + 382: timer.track( + 407: timer.track("gh pr status", "rtk gh pr status", &stderr, &stderr); + 431: timer.track("gh pr status", "rtk gh pr status", &raw, &filtered); + 462: timer.track("gh issue list", "rtk gh issue list", &stderr, &stderr); + 510: timer.track("gh issue list", "rtk gh issue list", &raw, &filtered); + +18 + +📄 /Users/andrew/Programming/rtk/src/git.rs (22): + 69: timer.track( + 116: timer.track( + 153: timer.track( + 222: timer.track( + 364: timer.track( + 548: timer.track( + 577: timer.track("git status", "rtk git status", &raw_output, &formatted); + 631: timer.track( + 689: timer.track( + 698: timer.track( + +12 + +📄 /Users/andrew/Programming/rtk/src/go_cmd.rs (4): + 70: timer.track( + 113: timer.track( + 156: timer.track( + 201: timer.track( + +📄 /Users/andrew/Programming/rtk/src/golangci_cmd.rs (1): + 75: timer.track( + +📄 /Users/andrew/Programming/rtk/src/grep_cmd.rs (2): + 46: timer.track( + 110: timer.track( + +📄 /Users/andrew/Programming/rtk/src/json_cmd.rs (2): + 21: timer.track( + 46: timer.track("cat - (stdin)", "rtk json -", &content, &schema); + +📄 /Users/andrew/Programming/rtk/src/lint_cmd.rs (1): + 89: timer.track( + +📄 /Users/andrew/Programming/rtk/src/log_cmd.rs (2): + 20: timer.track( + 43: timer.track("log (stdin)", "rtk log (stdin)", &content, &result); + +📄 /Users/andrew/Programming/rtk/src/ls.rs (1): + 113: timer.track( + +📄 /Users/andrew/Programming/rtk/src/main.rs (1): + 1430: timer.track( + +📄 /Users/andrew/Programming/rtk/src/next_cmd.rs (1): + 47: timer.track("next build", "rtk next build", &raw, &filtered); + +📄 /Users/andrew/Programming/rtk/src/npm_cmd.rs (1): + 31: timer.track( + +📄 /Users/andrew/Programming/rtk/src/pip_cmd.rs (1): + 43: timer.track( + +📄 /.../src/playwright_cmd.rs (1): + 268: timer.track( + +📄 /Users/andrew/Programming/rtk/src/pnpm_cmd.rs (3): + 340: timer.track( + 396: timer.track("pnpm outdated", "rtk pnpm outdated", &combined, &filtered); + 442: timer.track( + +📄 /Users/andrew/Programming/rtk/src/prettier_cmd.rs (1): + 31: timer.track( + +📄 /Users/andrew/Programming/rtk/src/prisma_cmd.rs (3): + 74: timer.track("prisma generate", "rtk prisma generate", &raw, &filtered); + 130: timer.track(cmd_name, &format!("rtk {}", cmd_name), &raw, &filtered); + 163: timer.track("prisma db push", "rtk prisma db push", &raw, &filtered); + +📄 /Users/andrew/Programming/rtk/src/pytest_cmd.rs (1): + 63: timer.track( + +📄 /Users/andrew/Programming/rtk/src/read.rs (2): + 64: timer.track( + 131: timer.track("cat - (stdin)", "rtk read -", &content, &rtk_output); + +📄 /Users/andrew/Programming/rtk/src/ruff_cmd.rs (1): + 99: timer.track( + +📄 /Users/andrew/Programming/rtk/src/runner.rs (2): + 53: timer.track(command, "rtk run-err", &raw, &rtk); + 86: timer.track(command, "rtk run-test", &raw, &summary); + +📄 /Users/andrew/Programming/rtk/src/summary.rs (1): + 36: timer.track(command, "rtk summary", &raw, &summary); + +📄 /Users/andrew/Programming/rtk/src/tracking.rs (6): + 22: //! timer.track("ls -la", "rtk ls", input, output); + 736: /// timer.track("ls -la", "rtk ls", &input, &output); + 757: /// timer.track("cmd", "rtk cmd", "input", "output"); + 787: /// timer.track("ls -la", "rtk ls", input, output); + 878: /// timer.track("ls -la", "rtk ls", "input", "output"); + 988: timer.track("test cmd", "rtk test", "raw input data", "filtered"); + +📄 /Users/andrew/Programming/rtk/src/tree.rs (1): + 100: timer.track("tree", "rtk tree", &raw, &filtered); + +📄 /Users/andrew/Programming/rtk/src/tsc_cmd.rs (1): + 46: timer.track( + +📄 /Users/andrew/Programming/rtk/src/vitest_cmd.rs (1): + 265: timer.track("vitest run", "rtk vitest run", &combined, &filtered); + +📄 /Users/andrew/Programming/rtk/src/wget_cmd.rs (4): + 42: timer.track(&format!("wget {}", url), "rtk wget", &raw_output, &msg); + 47: timer.track(&format!("wget {}", url), "rtk wget", &raw_output, &msg); + 98: timer.track( + 109: timer.track(&format!("wget -O - {}", url), "rtk wget -o", &stderr, &msg); + +... +32 diff --git a/benchmarks/quality_samples/B2_rtk_rgai.txt b/benchmarks/quality_samples/B2_rtk_rgai.txt new file mode 100644 index 0000000..95bc0b7 --- /dev/null +++ b/benchmarks/quality_samples/B2_rtk_rgai.txt @@ -0,0 +1,93 @@ +🧠 37F for 'timer\.track\(' (scan 55F) + +📄 tracking.rs [11.5] + 987: std::thread::sleep(std::time::Duration::from_millis(10)); + 988: timer.track("test cmd", "rtk test", "raw input data", "filtered"); + ~ timer, track + + 999: let timer = TimedExecution::start(); + 1000: timer.track_passthrough("git tag", "rtk git tag (passthrough)"); + ~ timer, track + + +33 more lines + +📄 git.rs [10.7] + 39: fn run_diff(args: &[String], max_lines: Option, verbose: u8) -> Result<()> { + 40: let timer = tracking::TimedExecution::start(); + ~ timer, track + + 69: timer.track( + 70: &format!("git diff {}", args.join(" ")), + ~ timer, track + + +51 more lines + +📄 gh_cmd.rs [10.5] + 48: fn list_prs(args: &[String], _verbose: u8, ultra_compact: bool) -> Result<()> { + 49: let timer = tracking::TimedExecution::start(); + ~ timer, track + + 68: let stderr = String::from_utf8_lossy(&output.stderr).to_string(); + 69: timer.track("gh pr list", "rtk gh pr list", &stderr, &stderr); + 70: eprintln!("{}", stderr.trim()); + ~ timer, track + + +44 more lines + +📄 container.rs [9.9] + 27: fn docker_ps(_verbose: u8) -> Result<()> { + 28: let timer = tracking::TimedExecution::start(); + ~ timer, track + + 50: println!("{}", rtk); + 51: timer.track("docker ps", "rtk docker ps", &raw, &rtk); + 52: return Ok(()); + ~ timer, track + + +23 more lines + +📄 cc_economics.rs [9.4] + 429: fn display_summary(tracker: &Tracker, verbose: u8) -> Result<()> { + 430: let cc_monthly = + ~ track + + 544: fn display_daily(tracker: &Tracker, verbose: u8) -> Result<()> { + 545: let cc_daily = + ~ track + + +25 more lines + +📄 gain.rs [9.4] + 190: fn print_daily_full(tracker: &Tracker) -> Result<()> { + 191: let days = tracker.get_all_days()?; + ~ track + + 196: fn print_weekly(tracker: &Tracker) -> Result<()> { + 197: let weeks = tracker.get_by_week()?; + ~ track + + +24 more lines + +📄 pnpm_cmd.rs [9.1] + 294: fn run_list(depth: usize, args: &[String], verbose: u8) -> Result<()> { + 295: let timer = tracking::TimedExecution::start(); + ~ timer, track + + 340: timer.track( + 341: &format!("pnpm list --depth={}", depth), + ~ timer, track + + +8 more lines + +📄 go_cmd.rs [9.0] + 34: pub fn run_test(args: &[String], verbose: u8) -> Result<()> { + 35: let timer = tracking::TimedExecution::start(); + ~ timer, track + + 70: timer.track( + 71: &format!("go test {}", args.join(" ")), + ~ timer, track + + +7 more lines + +... +29F diff --git a/benchmarks/quality_samples/B3_grep.txt b/benchmarks/quality_samples/B3_grep.txt new file mode 100644 index 0000000..a7bc5b5 --- /dev/null +++ b/benchmarks/quality_samples/B3_grep.txt @@ -0,0 +1,48 @@ +/Users/andrew/Programming/rtk/src/pip_cmd.rs:82: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/pip_cmd.rs:117: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/pip_cmd.rs:150: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/pytest_cmd.rs:72: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/ls.rs:88: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/npm_cmd.rs:39: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:63: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:694: std::process::exit(status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/go_cmd.rs:79: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/go_cmd.rs:122: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/go_cmd.rs:165: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/go_cmd.rs:210: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/curl_cmd.rs:31: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/gain.rs:165: let max_val = data.iter().map(|(_, v)| *v).max().unwrap_or(1); +/Users/andrew/Programming/rtk/src/git.rs:63: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/git.rs:148: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/git.rs:184: std::process::exit(summary_output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/git.rs:351: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/git.rs:648: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/git.rs:1283: std::process::exit(status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:510: std::process::exit(status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/tree.rs:80: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/ruff_cmd.rs:108: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/tsc_cmd.rs:54: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/vitest_cmd.rs:268: std::process::exit(output.status.code().unwrap_or(1)) +/Users/andrew/Programming/rtk/src/main.rs:1332: std::process::exit(status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/main.rs:1344: std::process::exit(status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/main.rs:1439: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/prettier_cmd.rs:40: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/next_cmd.rs:51: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/container.rs:429: std::process::exit(status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/container.rs:453: std::process::exit(status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:71: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:162: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:329: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:409: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:464: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:544: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:635: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:719: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:796: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:860: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:898: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:944: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:985: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:1030: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:1078: std::process::exit(status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/playwright_cmd.rs:277: std::process::exit(output.status.code().unwrap_or(1)); diff --git a/benchmarks/quality_samples/B3_head_n.txt b/benchmarks/quality_samples/B3_head_n.txt new file mode 100644 index 0000000..a7bc5b5 --- /dev/null +++ b/benchmarks/quality_samples/B3_head_n.txt @@ -0,0 +1,48 @@ +/Users/andrew/Programming/rtk/src/pip_cmd.rs:82: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/pip_cmd.rs:117: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/pip_cmd.rs:150: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/pytest_cmd.rs:72: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/ls.rs:88: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/npm_cmd.rs:39: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:63: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:694: std::process::exit(status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/go_cmd.rs:79: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/go_cmd.rs:122: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/go_cmd.rs:165: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/go_cmd.rs:210: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/curl_cmd.rs:31: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/gain.rs:165: let max_val = data.iter().map(|(_, v)| *v).max().unwrap_or(1); +/Users/andrew/Programming/rtk/src/git.rs:63: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/git.rs:148: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/git.rs:184: std::process::exit(summary_output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/git.rs:351: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/git.rs:648: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/git.rs:1283: std::process::exit(status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:510: std::process::exit(status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/tree.rs:80: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/ruff_cmd.rs:108: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/tsc_cmd.rs:54: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/vitest_cmd.rs:268: std::process::exit(output.status.code().unwrap_or(1)) +/Users/andrew/Programming/rtk/src/main.rs:1332: std::process::exit(status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/main.rs:1344: std::process::exit(status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/main.rs:1439: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/prettier_cmd.rs:40: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/next_cmd.rs:51: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/container.rs:429: std::process::exit(status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/container.rs:453: std::process::exit(status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:71: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:162: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:329: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:409: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:464: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:544: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:635: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:719: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:796: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:860: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:898: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:944: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:985: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:1030: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:1078: std::process::exit(status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/playwright_cmd.rs:277: std::process::exit(output.status.code().unwrap_or(1)); diff --git a/benchmarks/quality_samples/B3_rtk_grep.txt b/benchmarks/quality_samples/B3_rtk_grep.txt new file mode 100644 index 0000000..13425a0 --- /dev/null +++ b/benchmarks/quality_samples/B3_rtk_grep.txt @@ -0,0 +1,87 @@ +🔍 48 in 20F: + +📄 /Users/andrew/Programming/rtk/src/cargo_cmd.rs (2): + 63: std::process::exit(output.status.code().unwrap_or(1)); + 694: std::process::exit(status.code().unwrap_or(1)); + +📄 /Users/andrew/Programming/rtk/src/container.rs (2): + 429: std::process::exit(status.code().unwrap_or(1)); + 453: std::process::exit(status.code().unwrap_or(1)); + +📄 /Users/andrew/Programming/rtk/src/curl_cmd.rs (1): + 31: std::process::exit(output.status.code().unwrap_or(1)); + +📄 /Users/andrew/Programming/rtk/src/gain.rs (1): + 165: let max_val = data.iter().map(|(_, v)| *v).max().unwrap_or(1); + +📄 /Users/andrew/Programming/rtk/src/gh_cmd.rs (15): + 71: std::process::exit(output.status.code().unwrap_or(1)); + 162: std::process::exit(output.status.code().unwrap_or(1)); + 329: std::process::exit(output.status.code().unwrap_or(1)); + 409: std::process::exit(output.status.code().unwrap_or(1)); + 464: std::process::exit(output.status.code().unwrap_or(1)); + 544: std::process::exit(output.status.code().unwrap_or(1)); + 635: std::process::exit(output.status.code().unwrap_or(1)); + 719: std::process::exit(output.status.code().unwrap_or(1)); + 796: std::process::exit(output.status.code().unwrap_or(1)); + 860: std::process::exit(output.status.code().unwrap_or(1)); + +5 + +📄 /Users/andrew/Programming/rtk/src/git.rs (6): + 63: std::process::exit(output.status.code().unwrap_or(1)); + 148: std::process::exit(output.status.code().unwrap_or(1)); + 184: std::process::exit(summary_output.status.code().unwrap_or(1)); + 351: std::process::exit(output.status.code().unwrap_or(1)); + 648: std::process::exit(output.status.code().unwrap_or(1)); + 1283: std::process::exit(status.code().unwrap_or(1)); + +📄 /Users/andrew/Programming/rtk/src/go_cmd.rs (4): + 79: std::process::exit(output.status.code().unwrap_or(1)); + 122: std::process::exit(output.status.code().unwrap_or(1)); + 165: std::process::exit(output.status.code().unwrap_or(1)); + 210: std::process::exit(output.status.code().unwrap_or(1)); + +📄 /Users/andrew/Programming/rtk/src/ls.rs (1): + 88: std::process::exit(output.status.code().unwrap_or(1)); + +📄 /Users/andrew/Programming/rtk/src/main.rs (3): + 1332: std::process::exit(status.code().unwrap_or(1)); + 1344: std::process::exit(status.code().unwrap_or(1)); + 1439: std::process::exit(output.status.code().unwrap_or(1)); + +📄 /Users/andrew/Programming/rtk/src/next_cmd.rs (1): + 51: std::process::exit(output.status.code().unwrap_or(1)); + +📄 /Users/andrew/Programming/rtk/src/npm_cmd.rs (1): + 39: std::process::exit(output.status.code().unwrap_or(1)); + +📄 /Users/andrew/Programming/rtk/src/pip_cmd.rs (3): + 82: std::process::exit(output.status.code().unwrap_or(1)); + 117: std::process::exit(output.status.code().unwrap_or(1)); + 150: std::process::exit(output.status.code().unwrap_or(1)); + +📄 /.../src/playwright_cmd.rs (1): + 277: std::process::exit(output.status.code().unwrap_or(1)); + +📄 /Users/andrew/Programming/rtk/src/pnpm_cmd.rs (1): + 510: std::process::exit(status.code().unwrap_or(1)); + +📄 /Users/andrew/Programming/rtk/src/prettier_cmd.rs (1): + 40: std::process::exit(output.status.code().unwrap_or(1)); + +📄 /Users/andrew/Programming/rtk/src/pytest_cmd.rs (1): + 72: std::process::exit(output.status.code().unwrap_or(1)); + +📄 /Users/andrew/Programming/rtk/src/ruff_cmd.rs (1): + 108: std::process::exit(output.status.code().unwrap_or(1)); + +📄 /Users/andrew/Programming/rtk/src/tree.rs (1): + 80: std::process::exit(output.status.code().unwrap_or(1)); + +📄 /Users/andrew/Programming/rtk/src/tsc_cmd.rs (1): + 54: std::process::exit(output.status.code().unwrap_or(1)); + +📄 /Users/andrew/Programming/rtk/src/vitest_cmd.rs (1): + 268: std::process::exit(output.status.code().unwrap_or(1)) + +... +5 diff --git a/benchmarks/quality_samples/B3_rtk_rgai.txt b/benchmarks/quality_samples/B3_rtk_rgai.txt new file mode 100644 index 0000000..7fce48e --- /dev/null +++ b/benchmarks/quality_samples/B3_rtk_rgai.txt @@ -0,0 +1,106 @@ +🧠 27F for '\.unwrap_or\(1\)' (scan 55F) + +📄 gh_cmd.rs [6.4] + 70: eprintln!("{}", stderr.trim()); + 71: std::process::exit(output.status.code().unwrap_or(1)); + 72: } + ~ unwrap_or + + 88: for pr in prs.iter().take(20) { + 89: let number = pr["number"].as_i64().unwrap_or(0); + 90: let title = pr["title"].as_str().unwrap_or("???"); + ~ unwrap_or + + +48 more lines + +📄 git.rs [5.7] + 62: eprintln!("{}", stderr); + 63: std::process::exit(output.status.code().unwrap_or(1)); + 64: } + ~ unwrap_or + + 109: println!("\n--- Changes ---"); + 110: let compacted = compact_diff(&diff_stdout, max_lines.unwrap_or(100)); + 111: println!("{}", compacted); + ~ unwrap_or + + +22 more lines + +📄 cc_economics.rs [5.6] + 600: for p in periods { + 601: let spent = p.cc_cost.map(format_usd).unwrap_or_else(|| "—".to_string()); + 602: let saved = p + ~ unwrap_or + + 604: .map(format_tokens) + 605: .unwrap_or_else(|| "—".to_string()); + 606: let weighted = p + ~ unwrap_or + + +20 more lines + +📄 container.rs [5.5] + 33: .map(|o| String::from_utf8_lossy(&o.stdout).to_string()) + 34: .unwrap_or_default(); + ~ unwrap_or + + 62: let name = parts[1]; + 63: let short_image = parts.get(3).unwrap_or(&"").split('/').last().unwrap_or(""); + 64: let ports = compact_ports(parts.get(4).unwrap_or(&"")); + ~ unwrap_or + + +17 more lines + +📄 deps.rs [5.1] + 11: let dir = if path.is_file() { + 12: path.parent().unwrap_or(Path::new(".")) + 13: } else { + ~ unwrap_or + + 27: found = true; + 28: raw.push_str(&fs::read_to_string(&cargo_path).unwrap_or_default()); + 29: rtk.push_str("📦 Rust (Cargo.toml):\n"); + ~ unwrap_or + + +11 more lines + +📄 cargo_cmd.rs [4.5] + 62: if !output.status.success() { + 63: std::process::exit(output.status.code().unwrap_or(1)); + 64: } + ~ unwrap_or + + 133: if trimmed.starts_with("Installing") { + 134: let rest = trimmed.strip_prefix("Installing").unwrap_or("").trim(); + 135: if !rest.is_empty() && !rest.starts_with('/') { + ~ unwrap_or + + +5 more lines + +📄 discover/provider.rs [4.5] + 66: .checked_sub(Duration::from_secs(days * 86400)) + 67: .unwrap_or(SystemTime::UNIX_EPOCH) + 68: }); + ~ unwrap_or + + 83: if let Some(filter) = project_filter { + 84: let dir_name = path.file_name().and_then(|n| n.to_str()).unwrap_or(""); + 85: if !dir_name.contains(filter) { + ~ unwrap_or + + +5 more lines + +📄 go_cmd.rs [4.4] + 78: if !output.status.success() { + 79: std::process::exit(output.status.code().unwrap_or(1)); + 80: } + ~ unwrap_or + + 121: if !output.status.success() { + 122: std::process::exit(output.status.code().unwrap_or(1)); + 123: } + ~ unwrap_or + + +4 more lines + +... +19F diff --git a/benchmarks/quality_samples/B4_grep.txt b/benchmarks/quality_samples/B4_grep.txt new file mode 100644 index 0000000..1824352 --- /dev/null +++ b/benchmarks/quality_samples/B4_grep.txt @@ -0,0 +1,41 @@ +/Users/andrew/Programming/rtk/src/pip_cmd.rs:254:#[cfg(test)] +/Users/andrew/Programming/rtk/src/pytest_cmd.rs:281:#[cfg(test)] +/Users/andrew/Programming/rtk/src/ls.rs:228:#[cfg(test)] +/Users/andrew/Programming/rtk/src/local_llm.rs:274:#[cfg(test)] +/Users/andrew/Programming/rtk/src/learn/detector.rs:352:#[cfg(test)] +/Users/andrew/Programming/rtk/src/learn/report.rs:118:#[cfg(test)] +/Users/andrew/Programming/rtk/src/discover/registry.rs:505:#[cfg(test)] +/Users/andrew/Programming/rtk/src/discover/provider.rs:237:#[cfg(test)] +/Users/andrew/Programming/rtk/src/npm_cmd.rs:80:#[cfg(test)] +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:699:#[cfg(test)] +/Users/andrew/Programming/rtk/src/ccusage.rs:217:#[cfg(test)] +/Users/andrew/Programming/rtk/src/go_cmd.rs:425:#[cfg(test)] +/Users/andrew/Programming/rtk/src/lint_cmd.rs:244:#[cfg(test)] +/Users/andrew/Programming/rtk/src/curl_cmd.rs:83:#[cfg(test)] +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:432:#[cfg(test)] +/Users/andrew/Programming/rtk/src/cc_economics.rs:829:#[cfg(test)] +/Users/andrew/Programming/rtk/src/find_cmd.rs:205:#[cfg(test)] +/Users/andrew/Programming/rtk/src/golangci_cmd.rs:195:#[cfg(test)] +/Users/andrew/Programming/rtk/src/git.rs:1288:#[cfg(test)] +/Users/andrew/Programming/rtk/src/runner.rs:244:#[cfg(test)] +/Users/andrew/Programming/rtk/src/parser/mod.rs:190:#[cfg(test)] +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:515:#[cfg(test)] +/Users/andrew/Programming/rtk/src/tree.rs:136:#[cfg(test)] +/Users/andrew/Programming/rtk/src/log_cmd.rs:218:#[cfg(test)] +/Users/andrew/Programming/rtk/src/ruff_cmd.rs:319:#[cfg(test)] +/Users/andrew/Programming/rtk/src/grep_cmd.rs:186:#[cfg(test)] +/Users/andrew/Programming/rtk/src/json_cmd.rs:146:#[cfg(test)] +/Users/andrew/Programming/rtk/src/read.rs:145:#[cfg(test)] +/Users/andrew/Programming/rtk/src/tsc_cmd.rs:175:#[cfg(test)] +/Users/andrew/Programming/rtk/src/vitest_cmd.rs:271:#[cfg(test)] +/Users/andrew/Programming/rtk/src/tracking.rs:890:#[cfg(test)] +/Users/andrew/Programming/rtk/src/main.rs:1468:#[cfg(test)] +/Users/andrew/Programming/rtk/src/init.rs:1090:#[cfg(test)] +/Users/andrew/Programming/rtk/src/diff_cmd.rs:214:#[cfg(test)] +/Users/andrew/Programming/rtk/src/filter.rs:368:#[cfg(test)] +/Users/andrew/Programming/rtk/src/display_helpers.rs:304:#[cfg(test)] +/Users/andrew/Programming/rtk/src/prettier_cmd.rs:141:#[cfg(test)] +/Users/andrew/Programming/rtk/src/next_cmd.rs:198:#[cfg(test)] +/Users/andrew/Programming/rtk/src/utils.rs:228:#[cfg(test)] +/Users/andrew/Programming/rtk/src/gh_cmd.rs:1084:#[cfg(test)] +/Users/andrew/Programming/rtk/src/playwright_cmd.rs:283:#[cfg(test)] diff --git a/benchmarks/quality_samples/B4_head_n.txt b/benchmarks/quality_samples/B4_head_n.txt new file mode 100644 index 0000000..1824352 --- /dev/null +++ b/benchmarks/quality_samples/B4_head_n.txt @@ -0,0 +1,41 @@ +/Users/andrew/Programming/rtk/src/pip_cmd.rs:254:#[cfg(test)] +/Users/andrew/Programming/rtk/src/pytest_cmd.rs:281:#[cfg(test)] +/Users/andrew/Programming/rtk/src/ls.rs:228:#[cfg(test)] +/Users/andrew/Programming/rtk/src/local_llm.rs:274:#[cfg(test)] +/Users/andrew/Programming/rtk/src/learn/detector.rs:352:#[cfg(test)] +/Users/andrew/Programming/rtk/src/learn/report.rs:118:#[cfg(test)] +/Users/andrew/Programming/rtk/src/discover/registry.rs:505:#[cfg(test)] +/Users/andrew/Programming/rtk/src/discover/provider.rs:237:#[cfg(test)] +/Users/andrew/Programming/rtk/src/npm_cmd.rs:80:#[cfg(test)] +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:699:#[cfg(test)] +/Users/andrew/Programming/rtk/src/ccusage.rs:217:#[cfg(test)] +/Users/andrew/Programming/rtk/src/go_cmd.rs:425:#[cfg(test)] +/Users/andrew/Programming/rtk/src/lint_cmd.rs:244:#[cfg(test)] +/Users/andrew/Programming/rtk/src/curl_cmd.rs:83:#[cfg(test)] +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:432:#[cfg(test)] +/Users/andrew/Programming/rtk/src/cc_economics.rs:829:#[cfg(test)] +/Users/andrew/Programming/rtk/src/find_cmd.rs:205:#[cfg(test)] +/Users/andrew/Programming/rtk/src/golangci_cmd.rs:195:#[cfg(test)] +/Users/andrew/Programming/rtk/src/git.rs:1288:#[cfg(test)] +/Users/andrew/Programming/rtk/src/runner.rs:244:#[cfg(test)] +/Users/andrew/Programming/rtk/src/parser/mod.rs:190:#[cfg(test)] +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:515:#[cfg(test)] +/Users/andrew/Programming/rtk/src/tree.rs:136:#[cfg(test)] +/Users/andrew/Programming/rtk/src/log_cmd.rs:218:#[cfg(test)] +/Users/andrew/Programming/rtk/src/ruff_cmd.rs:319:#[cfg(test)] +/Users/andrew/Programming/rtk/src/grep_cmd.rs:186:#[cfg(test)] +/Users/andrew/Programming/rtk/src/json_cmd.rs:146:#[cfg(test)] +/Users/andrew/Programming/rtk/src/read.rs:145:#[cfg(test)] +/Users/andrew/Programming/rtk/src/tsc_cmd.rs:175:#[cfg(test)] +/Users/andrew/Programming/rtk/src/vitest_cmd.rs:271:#[cfg(test)] +/Users/andrew/Programming/rtk/src/tracking.rs:890:#[cfg(test)] +/Users/andrew/Programming/rtk/src/main.rs:1468:#[cfg(test)] +/Users/andrew/Programming/rtk/src/init.rs:1090:#[cfg(test)] +/Users/andrew/Programming/rtk/src/diff_cmd.rs:214:#[cfg(test)] +/Users/andrew/Programming/rtk/src/filter.rs:368:#[cfg(test)] +/Users/andrew/Programming/rtk/src/display_helpers.rs:304:#[cfg(test)] +/Users/andrew/Programming/rtk/src/prettier_cmd.rs:141:#[cfg(test)] +/Users/andrew/Programming/rtk/src/next_cmd.rs:198:#[cfg(test)] +/Users/andrew/Programming/rtk/src/utils.rs:228:#[cfg(test)] +/Users/andrew/Programming/rtk/src/gh_cmd.rs:1084:#[cfg(test)] +/Users/andrew/Programming/rtk/src/playwright_cmd.rs:283:#[cfg(test)] diff --git a/benchmarks/quality_samples/B4_rtk_grep.txt b/benchmarks/quality_samples/B4_rtk_grep.txt new file mode 100644 index 0000000..adb0f0f --- /dev/null +++ b/benchmarks/quality_samples/B4_rtk_grep.txt @@ -0,0 +1,125 @@ +🔍 41 in 41F: + +📄 /Users/andrew/Programming/rtk/src/cargo_cmd.rs (1): + 699: #[cfg(test)] + +📄 /Users/andrew/Programming/rtk/src/cc_economics.rs (1): + 829: #[cfg(test)] + +📄 /Users/andrew/Programming/rtk/src/ccusage.rs (1): + 217: #[cfg(test)] + +📄 /Users/andrew/Programming/rtk/src/curl_cmd.rs (1): + 83: #[cfg(test)] + +📄 /Users/andrew/Programming/rtk/src/diff_cmd.rs (1): + 214: #[cfg(test)] + +📄 /.../discover/provider.rs (1): + 237: #[cfg(test)] + +📄 /.../discover/registry.rs (1): + 505: #[cfg(test)] + +📄 /.../src/display_helpers.rs (1): + 304: #[cfg(test)] + +📄 /Users/andrew/Programming/rtk/src/filter.rs (1): + 368: #[cfg(test)] + +📄 /Users/andrew/Programming/rtk/src/find_cmd.rs (1): + 205: #[cfg(test)] + +📄 /Users/andrew/Programming/rtk/src/gh_cmd.rs (1): + 1084: #[cfg(test)] + +📄 /Users/andrew/Programming/rtk/src/git.rs (1): + 1288: #[cfg(test)] + +📄 /Users/andrew/Programming/rtk/src/go_cmd.rs (1): + 425: #[cfg(test)] + +📄 /Users/andrew/Programming/rtk/src/golangci_cmd.rs (1): + 195: #[cfg(test)] + +📄 /Users/andrew/Programming/rtk/src/grep_cmd.rs (1): + 186: #[cfg(test)] + +📄 /Users/andrew/Programming/rtk/src/init.rs (1): + 1090: #[cfg(test)] + +📄 /Users/andrew/Programming/rtk/src/json_cmd.rs (1): + 146: #[cfg(test)] + +📄 /.../learn/detector.rs (1): + 352: #[cfg(test)] + +📄 /Users/andrew/Programming/rtk/src/learn/report.rs (1): + 118: #[cfg(test)] + +📄 /Users/andrew/Programming/rtk/src/lint_cmd.rs (1): + 244: #[cfg(test)] + +📄 /Users/andrew/Programming/rtk/src/local_llm.rs (1): + 274: #[cfg(test)] + +📄 /Users/andrew/Programming/rtk/src/log_cmd.rs (1): + 218: #[cfg(test)] + +📄 /Users/andrew/Programming/rtk/src/ls.rs (1): + 228: #[cfg(test)] + +📄 /Users/andrew/Programming/rtk/src/main.rs (1): + 1468: #[cfg(test)] + +📄 /Users/andrew/Programming/rtk/src/next_cmd.rs (1): + 198: #[cfg(test)] + +📄 /Users/andrew/Programming/rtk/src/npm_cmd.rs (1): + 80: #[cfg(test)] + +📄 /Users/andrew/Programming/rtk/src/parser/mod.rs (1): + 190: #[cfg(test)] + +📄 /Users/andrew/Programming/rtk/src/pip_cmd.rs (1): + 254: #[cfg(test)] + +📄 /.../src/playwright_cmd.rs (1): + 283: #[cfg(test)] + +📄 /Users/andrew/Programming/rtk/src/pnpm_cmd.rs (1): + 515: #[cfg(test)] + +📄 /Users/andrew/Programming/rtk/src/prettier_cmd.rs (1): + 141: #[cfg(test)] + +📄 /Users/andrew/Programming/rtk/src/prisma_cmd.rs (1): + 432: #[cfg(test)] + +📄 /Users/andrew/Programming/rtk/src/pytest_cmd.rs (1): + 281: #[cfg(test)] + +📄 /Users/andrew/Programming/rtk/src/read.rs (1): + 145: #[cfg(test)] + +📄 /Users/andrew/Programming/rtk/src/ruff_cmd.rs (1): + 319: #[cfg(test)] + +📄 /Users/andrew/Programming/rtk/src/runner.rs (1): + 244: #[cfg(test)] + +📄 /Users/andrew/Programming/rtk/src/tracking.rs (1): + 890: #[cfg(test)] + +📄 /Users/andrew/Programming/rtk/src/tree.rs (1): + 136: #[cfg(test)] + +📄 /Users/andrew/Programming/rtk/src/tsc_cmd.rs (1): + 175: #[cfg(test)] + +📄 /Users/andrew/Programming/rtk/src/utils.rs (1): + 228: #[cfg(test)] + +📄 /Users/andrew/Programming/rtk/src/vitest_cmd.rs (1): + 271: #[cfg(test)] + diff --git a/benchmarks/quality_samples/B4_rtk_rgai.txt b/benchmarks/quality_samples/B4_rtk_rgai.txt new file mode 100644 index 0000000..426c059 --- /dev/null +++ b/benchmarks/quality_samples/B4_rtk_rgai.txt @@ -0,0 +1,101 @@ +🧠 45F for '#\[cfg\(test\)\]' (scan 55F) + +📄 vitest_cmd.rs [11.2] + 13: #[derive(Debug, Deserialize)] + 14: struct VitestJsonOutput { + 15: #[serde(rename = "testResults")] + ~ test + + 31: #[derive(Debug, Deserialize)] + 32: struct VitestTestFile { + 33: name: String, + ~ test + + +74 more lines + +📄 pytest_cmd.rs [11.0] + 90: /// Parse pytest output using state machine + 91: fn filter_pytest_output(output: &str) -> String { + 92: let mut state = ParseState::Header; + ~ test + + 170: fn build_pytest_summary(summary: &str, _test_files: &[String], failures: &[String]) -> String { + 171: // Parse summary line + ~ test + + +59 more lines + +📄 cargo_cmd.rs [10.5] + 73: fn run_test(args: &[String], verbose: u8) -> Result<()> { + 74: run_cargo_filtered("test", args, verbose, filter_cargo_test) + ~ test + + 364: #[derive(Debug, Default, Clone)] + 365: struct AggregatedTestResult { + 366: passed: usize, + ~ test + + +118 more lines + +📄 init.rs [9.6] + 1095: #[test] + 1096: fn test_init_mentions_all_top_level_commands() { + 1097: for cmd in [ + ~ test + + 1122: #[test] + 1123: fn test_init_has_version_marker() { + 1124: assert!( + ~ test + + +48 more lines + +📄 go_cmd.rs [9.5] + 10: #[allow(dead_code)] + 11: struct GoTestEvent { + 12: #[serde(rename = "Time")] + ~ test + + 34: pub fn run_test(args: &[String], verbose: u8) -> Result<()> { + 35: let timer = tracking::TimedExecution::start(); + ~ test + + +45 more lines + +📄 discover/registry.rs [9.3] + 510: #[test] + 511: fn test_classify_git_status() { + 512: assert_eq!( + ~ test + + 523: #[test] + 524: fn test_classify_git_diff_cached() { + 525: assert_eq!( + ~ test + + +37 more lines + +📄 parser/README.md [9.2] + 47: struct VitestParser; + ~ test + + 52: fn parse(input: &str) -> ParseResult { + 53: // Tier 1: Try JSON parsing + ~ test + + +32 more lines + +📄 playwright_cmd.rs [9.1] + 42: #[derive(Debug, Deserialize)] + 43: struct PlaywrightTest { + 44: title: String, + ~ test + + 51: #[derive(Debug, Deserialize)] + 52: struct PlaywrightTestResult { + 53: #[serde(rename = "status")] + ~ test + + +29 more lines + +... +37F diff --git a/benchmarks/quality_samples/B5_grep.txt b/benchmarks/quality_samples/B5_grep.txt new file mode 100644 index 0000000..fd43ecb --- /dev/null +++ b/benchmarks/quality_samples/B5_grep.txt @@ -0,0 +1,6 @@ +/Users/andrew/Programming/rtk/src/learn/report.rs:71: let mut grouped: HashMap> = HashMap::new(); +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:581: let mut by_rule: HashMap> = HashMap::new(); +/Users/andrew/Programming/rtk/src/find_cmd.rs:111: let mut by_dir: HashMap> = HashMap::new(); +/Users/andrew/Programming/rtk/src/parser/formatter.rs:126: let mut by_rule: std::collections::HashMap> = +/Users/andrew/Programming/rtk/src/grep_cmd.rs:55: let mut by_file: HashMap> = HashMap::new(); +/Users/andrew/Programming/rtk/src/tsc_cmd.rs:118: let mut by_file: HashMap> = HashMap::new(); diff --git a/benchmarks/quality_samples/B5_head_n.txt b/benchmarks/quality_samples/B5_head_n.txt new file mode 100644 index 0000000..fd43ecb --- /dev/null +++ b/benchmarks/quality_samples/B5_head_n.txt @@ -0,0 +1,6 @@ +/Users/andrew/Programming/rtk/src/learn/report.rs:71: let mut grouped: HashMap> = HashMap::new(); +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:581: let mut by_rule: HashMap> = HashMap::new(); +/Users/andrew/Programming/rtk/src/find_cmd.rs:111: let mut by_dir: HashMap> = HashMap::new(); +/Users/andrew/Programming/rtk/src/parser/formatter.rs:126: let mut by_rule: std::collections::HashMap> = +/Users/andrew/Programming/rtk/src/grep_cmd.rs:55: let mut by_file: HashMap> = HashMap::new(); +/Users/andrew/Programming/rtk/src/tsc_cmd.rs:118: let mut by_file: HashMap> = HashMap::new(); diff --git a/benchmarks/quality_samples/B5_rtk_grep.txt b/benchmarks/quality_samples/B5_rtk_grep.txt new file mode 100644 index 0000000..ca724de --- /dev/null +++ b/benchmarks/quality_samples/B5_rtk_grep.txt @@ -0,0 +1,20 @@ +🔍 6 in 6F: + +📄 /Users/andrew/Programming/rtk/src/cargo_cmd.rs (1): + 581: let mut by_rule: HashMap> = HashMap::new(); + +📄 /Users/andrew/Programming/rtk/src/find_cmd.rs (1): + 111: let mut by_dir: HashMap> = HashMap::new(); + +📄 /Users/andrew/Programming/rtk/src/grep_cmd.rs (1): + 55: let mut by_file: HashMap> = HashMap::new(); + +📄 /Users/andrew/Programming/rtk/src/learn/report.rs (1): + 71: let mut grouped: HashMap> = HashMap::new(); + +📄 /.../parser/formatter.rs (1): + 126: let mut by_rule: std::collections::HashMap> = + +📄 /Users/andrew/Programming/rtk/src/tsc_cmd.rs (1): + 118: let mut by_file: HashMap> = HashMap::new(); + diff --git a/benchmarks/quality_samples/B5_rtk_rgai.txt b/benchmarks/quality_samples/B5_rtk_rgai.txt new file mode 100644 index 0000000..4493807 --- /dev/null +++ b/benchmarks/quality_samples/B5_rtk_rgai.txt @@ -0,0 +1,96 @@ +🧠 55F for 'HashMap String { + 581: let mut by_rule: HashMap> = HashMap::new(); + 582: let mut error_count = 0; + ~ hashmap, string, str, vec + + 18: pub fn run(cmd: CargoCommand, args: &[String], verbose: u8) -> Result<()> { + 19: match cmd { + ~ string, str + + +115 more lines + +📄 tsc_cmd.rs [20.2] + 117: // Group by file + 118: let mut by_file: HashMap> = HashMap::new(); + 119: for err in &errors { + ~ hashmap, string, str, vec + + 8: pub fn run(args: &[String], verbose: u8) -> Result<()> { + 9: let timer = tracking::TimedExecution::start(); + ~ string, str + + +41 more lines + +📄 parser/formatter.rs [20.2] + 125: // Group by rule_id + 126: let mut by_rule: std::collections::HashMap> = + 127: std::collections::HashMap::new(); + ~ hashmap, string, str, vec + + 27: /// Format as compact summary (default) + 28: fn format_compact(&self) -> String; + ~ string, str + + +39 more lines + +📄 learn/report.rs [20.1] + 70: // Group by base command + 71: let mut grouped: HashMap> = HashMap::new(); + 72: for rule in rules { + ~ hashmap, string, str, vec + + 110: fn capitalize_first(s: &str) -> String { + 111: let mut chars = s.chars(); + ~ string, str + + +36 more lines + +📄 grep_cmd.rs [19.9] + 55: let mut by_file: HashMap> = HashMap::new(); + 56: let mut total = 0; + ~ hashmap, string, str, vec + + 120: fn clean_line(line: &str, max_len: usize, context_only: bool, pattern: &str) -> String { + 121: let trimmed = line.trim(); + ~ string, str + + +28 more lines + +📄 find_cmd.rs [19.3] + 110: // Group by directory + 111: let mut by_dir: HashMap> = HashMap::new(); + ~ hashmap, string, str, vec + + 170: // Extension summary + 171: let mut by_ext: HashMap = HashMap::new(); + 172: for file in &files { + ~ hashmap, string, str + + +22 more lines + +📄 local_llm.rs [15.8] + 128: fn extract_imports(content: &str, lang: &Language) -> Vec { + 129: let pattern = match lang { + ~ string, str, vec + + 167: fn extract_functions(content: &str, lang: &Language) -> Vec { + 168: let pattern = match lang { + ~ string, str, vec + + +49 more lines + +📄 tracking.rs [15.8] + 399: fn get_by_command(&self) -> Result> { + 400: let mut stmt = self.conn.prepare( + ~ string, str, vec + + 421: fn get_by_day(&self) -> Result> { + 422: let mut stmt = self.conn.prepare( + ~ string, str, vec + + +45 more lines + +... +47F diff --git a/benchmarks/quality_samples/B6_grep.txt b/benchmarks/quality_samples/B6_grep.txt new file mode 100644 index 0000000..b44680c --- /dev/null +++ b/benchmarks/quality_samples/B6_grep.txt @@ -0,0 +1,12 @@ +/Users/andrew/Programming/rtk/src/learn/detector.rs:48:lazy_static! { +/Users/andrew/Programming/rtk/src/discover/registry.rs:303:lazy_static! { +/Users/andrew/Programming/rtk/src/runner.rs:91: lazy_static::lazy_static! { +/Users/andrew/Programming/rtk/src/tsc_cmd.rs:59: lazy_static::lazy_static! { +/Users/andrew/Programming/rtk/src/vitest_cmd.rs:122: lazy_static::lazy_static! { +/Users/andrew/Programming/rtk/src/filter.rs:149:lazy_static! { +/Users/andrew/Programming/rtk/src/filter.rs:230:lazy_static! { +/Users/andrew/Programming/rtk/src/next_cmd.rs:59: lazy_static::lazy_static! { +/Users/andrew/Programming/rtk/src/next_cmd.rs:189: lazy_static::lazy_static! { +/Users/andrew/Programming/rtk/src/utils.rs:48: lazy_static::lazy_static! { +/Users/andrew/Programming/rtk/src/playwright_cmd.rs:141: lazy_static::lazy_static! { +/Users/andrew/Programming/rtk/src/playwright_cmd.rs:197: lazy_static::lazy_static! { diff --git a/benchmarks/quality_samples/B6_head_n.txt b/benchmarks/quality_samples/B6_head_n.txt new file mode 100644 index 0000000..b44680c --- /dev/null +++ b/benchmarks/quality_samples/B6_head_n.txt @@ -0,0 +1,12 @@ +/Users/andrew/Programming/rtk/src/learn/detector.rs:48:lazy_static! { +/Users/andrew/Programming/rtk/src/discover/registry.rs:303:lazy_static! { +/Users/andrew/Programming/rtk/src/runner.rs:91: lazy_static::lazy_static! { +/Users/andrew/Programming/rtk/src/tsc_cmd.rs:59: lazy_static::lazy_static! { +/Users/andrew/Programming/rtk/src/vitest_cmd.rs:122: lazy_static::lazy_static! { +/Users/andrew/Programming/rtk/src/filter.rs:149:lazy_static! { +/Users/andrew/Programming/rtk/src/filter.rs:230:lazy_static! { +/Users/andrew/Programming/rtk/src/next_cmd.rs:59: lazy_static::lazy_static! { +/Users/andrew/Programming/rtk/src/next_cmd.rs:189: lazy_static::lazy_static! { +/Users/andrew/Programming/rtk/src/utils.rs:48: lazy_static::lazy_static! { +/Users/andrew/Programming/rtk/src/playwright_cmd.rs:141: lazy_static::lazy_static! { +/Users/andrew/Programming/rtk/src/playwright_cmd.rs:197: lazy_static::lazy_static! { diff --git a/benchmarks/quality_samples/B6_rtk_grep.txt b/benchmarks/quality_samples/B6_rtk_grep.txt new file mode 100644 index 0000000..299cb58 --- /dev/null +++ b/benchmarks/quality_samples/B6_rtk_grep.txt @@ -0,0 +1,32 @@ +🔍 12 in 9F: + +📄 /.../discover/registry.rs (1): + 303: lazy_static! { + +📄 /Users/andrew/Programming/rtk/src/filter.rs (2): + 149: lazy_static! { + 230: lazy_static! { + +📄 /.../learn/detector.rs (1): + 48: lazy_static! { + +📄 /Users/andrew/Programming/rtk/src/next_cmd.rs (2): + 59: lazy_static::lazy_static! { + 189: lazy_static::lazy_static! { + +📄 /.../src/playwright_cmd.rs (2): + 141: lazy_static::lazy_static! { + 197: lazy_static::lazy_static! { + +📄 /Users/andrew/Programming/rtk/src/runner.rs (1): + 91: lazy_static::lazy_static! { + +📄 /Users/andrew/Programming/rtk/src/tsc_cmd.rs (1): + 59: lazy_static::lazy_static! { + +📄 /Users/andrew/Programming/rtk/src/utils.rs (1): + 48: lazy_static::lazy_static! { + +📄 /Users/andrew/Programming/rtk/src/vitest_cmd.rs (1): + 122: lazy_static::lazy_static! { + diff --git a/benchmarks/quality_samples/B6_rtk_rgai.txt b/benchmarks/quality_samples/B6_rtk_rgai.txt new file mode 100644 index 0000000..ea8a31f --- /dev/null +++ b/benchmarks/quality_samples/B6_rtk_rgai.txt @@ -0,0 +1,72 @@ +🧠 9F for 'lazy_static!' (scan 55F) + +📄 filter.rs [12.6] + 149: lazy_static! { + 150: static ref MULTIPLE_BLANK_LINES: Regex = Regex::new(r"\n{3,}").unwrap(); + ~ lazy_static + + 230: lazy_static! { + 231: static ref IMPORT_PATTERN: Regex = + ~ lazy_static + + +1 more lines + +📄 next_cmd.rs [12.3] + 58: fn filter_next_build(output: &str) -> String { + 59: lazy_static::lazy_static! { + 60: // Route line pattern: ○ /dashboard 1.2 kB 132 kB + ~ lazy_static + + 188: fn extract_time(line: &str) -> Option { + 189: lazy_static::lazy_static! { + 190: static ref TIME_RE: Regex = Regex::new(r"(\d+(?:\.\d+)?)\s*(s|ms)").unwrap(); + ~ lazy_static + +📄 playwright_cmd.rs [12.3] + 140: fn extract_playwright_regex(output: &str) -> Option { + 141: lazy_static::lazy_static! { + 142: static ref SUMMARY_RE: Regex = Regex::new( + ~ lazy_static + + 196: fn extract_failures_regex(output: &str) -> Vec { + 197: lazy_static::lazy_static! { + 198: static ref TEST_PATTERN: Regex = Regex::new( + ~ lazy_static + +📄 discover/registry.rs [9.6] + 303: lazy_static! { + 304: static ref REGEX_SET: RegexSet = RegexSet::new(PATTERNS).expect("invalid regex patterns"); + ~ lazy_static + + 1: use lazy_static::lazy_static; + 2: use regex::{Regex, RegexSet}; + ~ lazy_static + +📄 learn/detector.rs [9.6] + 48: lazy_static! { + 49: static ref UNKNOWN_FLAG_RE: Regex = Regex::new( + ~ lazy_static + + 1: use lazy_static::lazy_static; + 2: use regex::Regex; + ~ lazy_static + +📄 runner.rs [8.4] + 90: fn filter_errors(output: &str) -> String { + 91: lazy_static::lazy_static! { + 92: static ref ERROR_PATTERNS: Vec = vec![ + ~ lazy_static + +📄 tsc_cmd.rs [8.4] + 58: fn filter_tsc_output(output: &str) -> String { + 59: lazy_static::lazy_static! { + 60: // Pattern: src/file.ts(12,5): error TS2322: Type 'string' is not assignable to type 'number'. + ~ lazy_static + +📄 utils.rs [8.4] + 47: pub fn strip_ansi(text: &str) -> String { + 48: lazy_static::lazy_static! { + 49: static ref ANSI_RE: Regex = Regex::new(r"\x1b\[[0-9;]*[a-zA-Z]").unwrap(); + ~ lazy_static + +... +1F diff --git a/benchmarks/quality_samples/C10_grep.txt b/benchmarks/quality_samples/C10_grep.txt new file mode 100644 index 0000000..e69de29 diff --git a/benchmarks/quality_samples/C10_head_n.txt b/benchmarks/quality_samples/C10_head_n.txt new file mode 100644 index 0000000..e69de29 diff --git a/benchmarks/quality_samples/C10_rtk_grep.txt b/benchmarks/quality_samples/C10_rtk_grep.txt new file mode 100644 index 0000000..dcf3751 --- /dev/null +++ b/benchmarks/quality_samples/C10_rtk_grep.txt @@ -0,0 +1 @@ +🔍 0 for 'SQLite retention cleanup policy' diff --git a/benchmarks/quality_samples/C10_rtk_rgai.txt b/benchmarks/quality_samples/C10_rtk_rgai.txt new file mode 100644 index 0000000..8183c91 --- /dev/null +++ b/benchmarks/quality_samples/C10_rtk_rgai.txt @@ -0,0 +1,27 @@ +🧠 2F for 'SQLite retention cleanup policy' (scan 55F) + +📄 tracking.rs [7.3] + 314: fn cleanup_old(&self) -> Result<()> { + 315: let cutoff = Utc::now() - chrono::Duration::days(HISTORY_DAYS); + ~ cleanup + + 9: //! - Storage: SQLite database (~/.local/share/rtk/tracking.db) + 10: //! - Retention: 90-day automatic cleanup + 11: //! - Metrics: Input/output tokens, savings %, execution time + ~ retention, cleanup + + +2 more lines + +📄 init.rs [6.9] + 1198: #[test] + 1199: fn test_search_priority_policy_in_init_and_slim_templates() { + 1200: let policy = "Search priority (mandatory): rgai > rg > grep."; + ~ policy + + 1202: RTK_INSTRUCTIONS.contains(policy), + 1203: "RTK_INSTRUCTIONS must include strict search priority policy" + 1204: ); + ~ policy + + +4 more lines + diff --git a/benchmarks/quality_samples/C1_grep.txt b/benchmarks/quality_samples/C1_grep.txt new file mode 100644 index 0000000..e69de29 diff --git a/benchmarks/quality_samples/C1_head_n.txt b/benchmarks/quality_samples/C1_head_n.txt new file mode 100644 index 0000000..e69de29 diff --git a/benchmarks/quality_samples/C1_rtk_grep.txt b/benchmarks/quality_samples/C1_rtk_grep.txt new file mode 100644 index 0000000..2e2c7cd --- /dev/null +++ b/benchmarks/quality_samples/C1_rtk_grep.txt @@ -0,0 +1 @@ +🔍 0 for 'token savings tracking database' diff --git a/benchmarks/quality_samples/C1_rtk_rgai.txt b/benchmarks/quality_samples/C1_rtk_rgai.txt new file mode 100644 index 0000000..e0f2ebb --- /dev/null +++ b/benchmarks/quality_samples/C1_rtk_rgai.txt @@ -0,0 +1,102 @@ +🧠 47F for 'token savings tracking database' (scan 55F) + +📄 cc_economics.rs [17.3] + 433: .get_by_month() + 434: .context("Failed to load monthly token savings from database")?; + 435: let periods = merge_monthly(cc_monthly, rtk_monthly); + ~ token, savings, saving, database + + 548: .get_all_days() + 549: .context("Failed to load daily token savings from database")?; + 550: let periods = merge_daily(cc_daily, rtk_daily); + ~ token, savings, saving, database + + +299 more lines + +📄 tracking.rs [17.2] + 1: //! Token savings tracking and analytics system. + 2: //! + ~ token, savings, saving, tracking, track + + 295: self.conn.execute( + 296: "INSERT INTO commands (timestamp, original_cmd, rtk_cmd, input_tokens, output_tokens, saved_tokens, savings_pct, exec_time_ms) + 297: VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8)", + ~ token, savings, saving + + +166 more lines + +📄 gain.rs [15.8] + 29: .get_summary() + 30: .context("Failed to load token savings summary from database")?; + ~ token, savings, saving, database + + 33: println!("No tracking data yet."); + 34: println!("Run some rtk commands to start tracking savings."); + 35: return Ok(()); + ~ savings, saving, tracking, track + + +61 more lines + +📄 display_helpers.rs [14.4] + 45: /// Savings percentage + 46: fn savings_pct(&self) -> f64; + ~ savings, saving + + 173: fn savings_pct(&self) -> f64 { + 174: self.savings_pct + ~ savings, saving + + +60 more lines + +📄 discover/registry.rs [13.5] + 694: #[test] + 695: fn test_classify_cargo_clippy_savings() { + 696: assert_eq!( + ~ savings, saving + + 7: category: &'static str, + 8: savings_pct: f64, + 9: subcmd_savings: &'static [(&'static str, f64)], + ~ savings, saving + + +72 more lines + +📄 config.rs [12.1] + 15: #[derive(Debug, Serialize, Deserialize)] + 16: pub struct TrackingConfig { + 17: pub enabled: bool, + ~ tracking, track + + 23: impl Default for TrackingConfig { + 24: fn default() -> Self { + ~ tracking, track + + +3 more lines + +📄 discover/report.rs [12.0] + 30: pub category: &'static str, + 31: pub estimated_savings_tokens: usize, + 32: pub estimated_savings_pct: f64, + ~ token, savings, saving + + 59: .iter() + 60: .map(|s| s.estimated_savings_tokens) + 61: .sum() + ~ token, savings, saving + + +15 more lines + +📄 discover/mod.rs [11.9] + 114: let savings = + 115: (output_tokens as f64 * estimated_savings_pct / 100.0) as usize; + 116: bucket.total_output_tokens += savings; + ~ token, savings, saving + + 177: category: bucket.category, + 178: estimated_savings_tokens: bucket.total_output_tokens, + 179: estimated_savings_pct: bucket.savings_pct, + ~ token, savings, saving + + +13 more lines + +... +39F diff --git a/benchmarks/quality_samples/C2_grep.txt b/benchmarks/quality_samples/C2_grep.txt new file mode 100644 index 0000000..e69de29 diff --git a/benchmarks/quality_samples/C2_head_n.txt b/benchmarks/quality_samples/C2_head_n.txt new file mode 100644 index 0000000..e69de29 diff --git a/benchmarks/quality_samples/C2_rtk_grep.txt b/benchmarks/quality_samples/C2_rtk_grep.txt new file mode 100644 index 0000000..a00e1af --- /dev/null +++ b/benchmarks/quality_samples/C2_rtk_grep.txt @@ -0,0 +1 @@ +🔍 0 for 'exit code preservation' diff --git a/benchmarks/quality_samples/C2_rtk_rgai.txt b/benchmarks/quality_samples/C2_rtk_rgai.txt new file mode 100644 index 0000000..e245212 --- /dev/null +++ b/benchmarks/quality_samples/C2_rtk_rgai.txt @@ -0,0 +1,96 @@ +🧠 8F for 'exit code preservation' (scan 55F) + +📄 gh_cmd.rs [4.8] + 70: eprintln!("{}", stderr.trim()); + 71: std::process::exit(output.status.code().unwrap_or(1)); + 72: } + ~ exit + + 161: eprintln!("{}", stderr.trim()); + 162: std::process::exit(output.status.code().unwrap_or(1)); + 163: } + ~ exit + + +13 more lines + +📄 git.rs [4.0] + 62: eprintln!("{}", stderr); + 63: std::process::exit(output.status.code().unwrap_or(1)); + 64: } + ~ exit + + 147: eprintln!("{}", stderr); + 148: std::process::exit(output.status.code().unwrap_or(1)); + 149: } + ~ exit + + +4 more lines + +📄 go_cmd.rs [3.6] + 78: if !output.status.success() { + 79: std::process::exit(output.status.code().unwrap_or(1)); + 80: } + ~ exit + + 121: if !output.status.success() { + 122: std::process::exit(output.status.code().unwrap_or(1)); + 123: } + ~ exit + + +2 more lines + +📄 main.rs [3.4] + 1331: if !status.success() { + 1332: std::process::exit(status.code().unwrap_or(1)); + 1333: } + ~ exit + + 1343: if !status.success() { + 1344: std::process::exit(status.code().unwrap_or(1)); + 1345: } + ~ exit + + +1 more lines + +📄 pip_cmd.rs [3.4] + 81: if !output.status.success() { + 82: std::process::exit(output.status.code().unwrap_or(1)); + 83: } + ~ exit + + 116: if !output.status.success() { + 117: std::process::exit(output.status.code().unwrap_or(1)); + 118: } + ~ exit + + +1 more lines + +📄 cargo_cmd.rs [3.1] + 62: if !output.status.success() { + 63: std::process::exit(output.status.code().unwrap_or(1)); + 64: } + ~ exit + + 693: if !status.success() { + 694: std::process::exit(status.code().unwrap_or(1)); + 695: } + ~ exit + +📄 container.rs [3.1] + 428: if !status.success() { + 429: std::process::exit(status.code().unwrap_or(1)); + 430: } + ~ exit + + 452: if !status.success() { + 453: std::process::exit(status.code().unwrap_or(1)); + 454: } + ~ exit + +📄 utils.rs [2.5] + 77: let stderr = String::from_utf8_lossy(&output.stderr).to_string(); + 78: let exit_code = output.status.code().unwrap_or(-1); + ~ exit + + +1 more lines + diff --git a/benchmarks/quality_samples/C3_grep.txt b/benchmarks/quality_samples/C3_grep.txt new file mode 100644 index 0000000..e69de29 diff --git a/benchmarks/quality_samples/C3_head_n.txt b/benchmarks/quality_samples/C3_head_n.txt new file mode 100644 index 0000000..e69de29 diff --git a/benchmarks/quality_samples/C3_rtk_grep.txt b/benchmarks/quality_samples/C3_rtk_grep.txt new file mode 100644 index 0000000..9139db9 --- /dev/null +++ b/benchmarks/quality_samples/C3_rtk_grep.txt @@ -0,0 +1 @@ +🔍 0 for 'language aware code filtering' diff --git a/benchmarks/quality_samples/C3_rtk_rgai.txt b/benchmarks/quality_samples/C3_rtk_rgai.txt new file mode 100644 index 0000000..613e7ef --- /dev/null +++ b/benchmarks/quality_samples/C3_rtk_rgai.txt @@ -0,0 +1,103 @@ +🧠 36F for 'language aware code filtering' (scan 55F) + +📄 filter.rs [15.7] + 35: pub trait FilterStrategy { + 36: fn filter(&self, content: &str, lang: &Language) -> String; + 37: #[allow(dead_code)] + ~ language, filter + + 137: impl FilterStrategy for NoFilter { + 138: fn filter(&self, content: &str, _lang: &Language) -> String { + 139: content.to_string() + ~ language, filter + + +63 more lines + +📄 cargo_cmd.rs [10.5] + 28: /// Generic cargo command runner with filtering + 29: fn run_cargo_filtered(subcommand: &str, args: &[String], verbose: u8, filter_fn: F) -> Result<()> + 30: where + ~ filter + + 100: /// Filter cargo install output - strip dep compilation, keep installed/replaced/errors + 101: fn filter_cargo_install(output: &str) -> String { + 102: let mut errors: Vec = Vec::new(); + ~ filter + + +81 more lines + +📄 local_llm.rs [10.3] + 6: use crate::filter::Language; + ~ language, filter + + 36: fn analyze_code(content: &str, lang: &Language) -> CodeSummary { + 37: let lines: Vec<&str> = content.lines().collect(); + ~ language + + +44 more lines + +📄 git.rs [10.0] + 374: /// Filter git log output: truncate long messages, cap lines + 375: fn filter_log_output(output: &str, limit: usize) -> String { + 376: let lines: Vec<&str> = output.lines().collect(); + ~ filter + + 489: /// Minimal filtering for git status with user-provided args + 490: fn filter_status_with_args(output: &str) -> String { + 491: let mut result = Vec::new(); + ~ filter + + +47 more lines + +📄 go_cmd.rs [9.9] + 204: &raw, + 205: &raw, // No filtering for unsupported commands + 206: ); + ~ filtering, filter + + 216: /// Parse go test -json output (NDJSON format) + 217: fn filter_go_test_json(output: &str) -> String { + 218: let mut packages: HashMap = HashMap::new(); + ~ filter + + +26 more lines + +📄 tree.rs [9.2] + 105: fn filter_tree_output(raw: &str) -> String { + 106: let lines: Vec<&str> = raw.lines().collect(); + ~ filter + + 140: #[test] + 141: fn test_filter_removes_summary() { + 142: let input = ".\n├── src\n│ └── main.rs\n└── Cargo.toml\n\n2 directories, 3 files\n"; + ~ filter + + +20 more lines + +📄 prisma_cmd.rs [9.2] + 168: /// Filter prisma generate output - strip ASCII art, extract counts + 169: fn filter_prisma_generate(output: &str) -> String { + 170: let mut models = 0; + ~ filter + + 227: /// Filter migrate dev output - extract migration changes + 228: fn filter_migrate_dev(output: &str) -> String { + 229: let mut migration_name = String::new(); + ~ filter + + +19 more lines + +📄 pip_cmd.rs [9.1] + 168: /// Filter pip list JSON output + 169: fn filter_pip_list(output: &str) -> String { + 170: let packages: Vec = match serde_json::from_str(output) { + ~ filter + + 213: /// Filter pip outdated JSON output + 214: fn filter_pip_outdated(output: &str) -> String { + 215: let packages: Vec = match serde_json::from_str(output) { + ~ filter + + +18 more lines + +... +28F diff --git a/benchmarks/quality_samples/C4_grep.txt b/benchmarks/quality_samples/C4_grep.txt new file mode 100644 index 0000000..e69de29 diff --git a/benchmarks/quality_samples/C4_head_n.txt b/benchmarks/quality_samples/C4_head_n.txt new file mode 100644 index 0000000..e69de29 diff --git a/benchmarks/quality_samples/C4_rtk_grep.txt b/benchmarks/quality_samples/C4_rtk_grep.txt new file mode 100644 index 0000000..f2e4725 --- /dev/null +++ b/benchmarks/quality_samples/C4_rtk_grep.txt @@ -0,0 +1 @@ +🔍 0 for 'output grouping by file' diff --git a/benchmarks/quality_samples/C4_rtk_rgai.txt b/benchmarks/quality_samples/C4_rtk_rgai.txt new file mode 100644 index 0000000..655fca4 --- /dev/null +++ b/benchmarks/quality_samples/C4_rtk_rgai.txt @@ -0,0 +1,105 @@ +🧠 44F for 'output grouping by file' (scan 55F) + +📄 git.rs [11.3] + 374: /// Filter git log output: truncate long messages, cap lines + 375: fn filter_log_output(output: &str, limit: usize) -> String { + 376: let lines: Vec<&str> = output.lines().collect(); + ~ output + + 393: /// Format porcelain output into compact RTK status display + 394: fn format_status_output(porcelain: &str) -> String { + 395: let lines: Vec<&str> = porcelain.lines().collect(); + ~ output + + +175 more lines + +📄 cargo_cmd.rs [10.2] + 100: /// Filter cargo install output - strip dep compilation, keep installed/replaced/errors + 101: fn filter_cargo_install(output: &str) -> String { + 102: let mut errors: Vec = Vec::new(); + ~ output + + 272: /// Filter cargo build/check output - strip "Compiling"/"Checking" lines, keep errors + summary + 273: fn filter_cargo_build(output: &str) -> String { + 274: let mut errors: Vec = Vec::new(); + ~ output + + +57 more lines + +📄 go_cmd.rs [10.1] + 216: /// Parse go test -json output (NDJSON format) + 217: fn filter_go_test_json(output: &str) -> String { + 218: let mut packages: HashMap = HashMap::new(); + ~ output + + 340: /// Filter go build output - show only errors + 341: fn filter_go_build(output: &str) -> String { + 342: let mut errors: Vec = Vec::new(); + ~ output + + +54 more lines + +📄 learn/detector.rs [10.1] + 75: /// Filters out user rejections - requires actual error-indicating content + 76: pub fn is_command_error(is_error: bool, output: &str) -> bool { + 77: if !is_error { + ~ output + + 97: pub fn classify_error(output: &str) -> ErrorType { + 98: if UNKNOWN_FLAG_RE.is_match(output) { + ~ output + + +51 more lines + +📄 summary.rs [9.9] + 40: fn summarize_output(output: &str, command: &str, success: bool) -> String { + 41: let lines: Vec<&str> = output.lines().collect(); + ~ output + + 69: #[derive(Debug)] + 70: enum OutputType { + 71: TestResults, + ~ output + + +44 more lines + +📄 prisma_cmd.rs [9.7] + 168: /// Filter prisma generate output - strip ASCII art, extract counts + 169: fn filter_prisma_generate(output: &str) -> String { + 170: let mut models = 0; + ~ output + + 227: /// Filter migrate dev output - extract migration changes + 228: fn filter_migrate_dev(output: &str) -> String { + 229: let mut migration_name = String::new(); + ~ output + + +33 more lines + +📄 pip_cmd.rs [9.6] + 168: /// Filter pip list JSON output + 169: fn filter_pip_list(output: &str) -> String { + 170: let packages: Vec = match serde_json::from_str(output) { + ~ output + + 213: /// Filter pip outdated JSON output + 214: fn filter_pip_outdated(output: &str) -> String { + 215: let packages: Vec = match serde_json::from_str(output) { + ~ output + + +29 more lines + +📄 tracking.rs [9.6] + 788: /// ``` + 789: pub fn track(&self, original_cmd: &str, rtk_cmd: &str, input: &str, output: &str) { + 790: let elapsed_ms = self.start.elapsed().as_millis() as u64; + ~ output + + 880: #[deprecated(note = "Use TimedExecution instead")] + 881: pub fn track(original_cmd: &str, rtk_cmd: &str, input: &str, output: &str) { + 882: let input_tokens = estimate_tokens(input); + ~ output + + +29 more lines + +... +36F diff --git a/benchmarks/quality_samples/C5_grep.txt b/benchmarks/quality_samples/C5_grep.txt new file mode 100644 index 0000000..e69de29 diff --git a/benchmarks/quality_samples/C5_head_n.txt b/benchmarks/quality_samples/C5_head_n.txt new file mode 100644 index 0000000..e69de29 diff --git a/benchmarks/quality_samples/C5_rtk_grep.txt b/benchmarks/quality_samples/C5_rtk_grep.txt new file mode 100644 index 0000000..c1449c4 --- /dev/null +++ b/benchmarks/quality_samples/C5_rtk_grep.txt @@ -0,0 +1 @@ +🔍 0 for 'three tier parser degradation' diff --git a/benchmarks/quality_samples/C5_rtk_rgai.txt b/benchmarks/quality_samples/C5_rtk_rgai.txt new file mode 100644 index 0000000..012c2c4 --- /dev/null +++ b/benchmarks/quality_samples/C5_rtk_rgai.txt @@ -0,0 +1,95 @@ +🧠 10F for 'three tier parser degradation' (scan 55F) + +📄 parser/README.md [14.6] + 5: The parser infrastructure provides a unified, three-tier parsing system for tool outputs with graceful degradation: + ~ three, tier, parser, degradation + + 47: struct VitestParser; + ~ parser + + +40 more lines + +📄 parser/mod.rs [13.6] + 87: /// Parse with explicit tier preference (for testing/debugging) + 88: fn parse_with_tier(input: &str, max_tier: u8) -> ParseResult { + 89: let result = Self::parse(input); + ~ tier, parser + + 18: #[derive(Debug)] + 19: pub enum ParseResult { + 20: /// Tier 1: Full parse with complete structured data + ~ parser + + +38 more lines + +📄 playwright_cmd.rs [9.7] + 7: use crate::parser::{ + 8: emit_degradation_warning, emit_passthrough_warning, truncate_output, FormatMode, OutputParser, + 9: ParseResult, TestFailure, TestResult, TokenFormatter, + ~ parser, degradation + + 66: /// Parser for Playwright JSON output + 67: pub struct PlaywrightParser; + ~ parser + + +23 more lines + +📄 pnpm_cmd.rs [9.7] + 45: /// Parser for pnpm list output + 46: pub struct PnpmListParser; + ~ parser + + 51: fn parse(input: &str) -> ParseResult { + 52: // Tier 1: Try JSON parsing + ~ parser + + +33 more lines + +📄 vitest_cmd.rs [9.6] + 47: /// Parser for Vitest JSON output + 48: pub struct VitestParser; + ~ parser + + 53: fn parse(input: &str) -> ParseResult { + 54: // Tier 1: Try JSON parsing (with extraction fallback for pnpm/dotenv prefixes) + ~ parser + + +32 more lines + +📄 prettier_cmd.rs [8.7] + 46: /// Filter Prettier output - show only files that need formatting + 47: fn filter_prettier_output(output: &str) -> String { + 48: let mut files_to_format: Vec = Vec::new(); + ~ tier + + 8: let mut cmd = package_manager_exec("prettier"); + ~ tier + + +17 more lines + +📄 main.rs [4.9] + 28: mod npm_cmd; + 29: mod parser; + 30: mod pip_cmd; + ~ parser + + 48: use anyhow::{Context, Result}; + 49: use clap::{Parser, Subcommand}; + 50: use std::ffi::OsString; + ~ parser + + +9 more lines + +📄 gain.rs [3.4] + 10: quota: bool, + 11: tier: &str, + 12: daily: bool, + ~ tier + + 118: let (quota_tokens, tier_name) = match tier { + 119: "pro" => (ESTIMATED_PRO_MONTHLY, "Pro ($20/mo)"), + ~ tier + + +1 more lines + +... +2F diff --git a/benchmarks/quality_samples/C6_grep.txt b/benchmarks/quality_samples/C6_grep.txt new file mode 100644 index 0000000..e69de29 diff --git a/benchmarks/quality_samples/C6_head_n.txt b/benchmarks/quality_samples/C6_head_n.txt new file mode 100644 index 0000000..e69de29 diff --git a/benchmarks/quality_samples/C6_rtk_grep.txt b/benchmarks/quality_samples/C6_rtk_grep.txt new file mode 100644 index 0000000..3cc7bb5 --- /dev/null +++ b/benchmarks/quality_samples/C6_rtk_grep.txt @@ -0,0 +1 @@ +🔍 0 for 'ANSI color stripping cleanup' diff --git a/benchmarks/quality_samples/C6_rtk_rgai.txt b/benchmarks/quality_samples/C6_rtk_rgai.txt new file mode 100644 index 0000000..653a800 --- /dev/null +++ b/benchmarks/quality_samples/C6_rtk_rgai.txt @@ -0,0 +1,92 @@ +🧠 9F for 'ANSI color stripping cleanup' (scan 55F) + +📄 utils.rs [9.8] + 3: //! Provides common helpers used across rtk commands: + 4: //! - ANSI color code stripping + 5: //! - Text truncation + ~ ansi, color, stripping, stripp + + 46: /// ``` + 47: pub fn strip_ansi(text: &str) -> String { + 48: lazy_static::lazy_static! { + ~ ansi + + +11 more lines + +📄 discover/registry.rs [7.7] + 629: #[test] + 630: fn test_classify_env_prefix_stripped() { + 631: assert_eq!( + ~ stripp + + 642: #[test] + 643: fn test_classify_sudo_stripped() { + 644: assert_eq!( + ~ stripp + + +2 more lines + +📄 vitest_cmd.rs [6.1] + 323: #[test] + 324: fn test_strip_ansi() { + 325: let input = "\x1b[32m✓\x1b[0m test passed"; + ~ ansi + + 9: use crate::tracking; + 10: use crate::utils::{package_manager_exec, strip_ansi}; + ~ ansi + + +2 more lines + +📄 tracking.rs [6.1] + 314: fn cleanup_old(&self) -> Result<()> { + 315: let cutoff = Utc::now() - chrono::Duration::days(HISTORY_DAYS); + ~ cleanup + + 310: self.cleanup_old()?; + 311: Ok(()) + ~ cleanup + +📄 learn/detector.rs [5.4] + 123: /// Extract base command (first 1-2 tokens, stripping env prefixes) + 124: pub fn extract_base_command(cmd: &str) -> String { + ~ stripping, stripp + + 127: // Strip common env prefixes + 128: let stripped = trimmed + 129: .strip_prefix("RUST_BACKTRACE=1 ") + ~ stripp + + +1 more lines + +📄 config.rs [3.6] + 34: pub struct DisplayConfig { + 35: pub colors: bool, + 36: pub emoji: bool, + ~ color + + 42: Self { + 43: colors: true, + 44: emoji: true, + ~ color + +📄 next_cmd.rs [3.1] + 1: use crate::tracking; + 2: use crate::utils::{strip_ansi, truncate}; + 3: use anyhow::{Context, Result}; + ~ ansi + + 79: // Strip ANSI codes + 80: let clean_output = strip_ansi(output); + ~ ansi + +📄 playwright_cmd.rs [3.1] + 1: use crate::tracking; + 2: use crate::utils::{package_manager_exec, strip_ansi}; + 3: use anyhow::{Context, Result}; + ~ ansi + + 150: let clean_output = strip_ansi(output); + ~ ansi + +... +1F diff --git a/benchmarks/quality_samples/C7_grep.txt b/benchmarks/quality_samples/C7_grep.txt new file mode 100644 index 0000000..e69de29 diff --git a/benchmarks/quality_samples/C7_head_n.txt b/benchmarks/quality_samples/C7_head_n.txt new file mode 100644 index 0000000..e69de29 diff --git a/benchmarks/quality_samples/C7_rtk_grep.txt b/benchmarks/quality_samples/C7_rtk_grep.txt new file mode 100644 index 0000000..b943d03 --- /dev/null +++ b/benchmarks/quality_samples/C7_rtk_grep.txt @@ -0,0 +1 @@ +🔍 0 for 'hook installation settings json' diff --git a/benchmarks/quality_samples/C7_rtk_rgai.txt b/benchmarks/quality_samples/C7_rtk_rgai.txt new file mode 100644 index 0000000..4202941 --- /dev/null +++ b/benchmarks/quality_samples/C7_rtk_rgai.txt @@ -0,0 +1,104 @@ +🧠 26F for 'hook installation settings json' (scan 55F) + +📄 init.rs [19.3] + 479: /// Handles reading, checking, prompting, merging, backing up, and atomic writing + 480: fn patch_settings_json(hook_path: &Path, mode: PatchMode, verbose: u8) -> Result { + 481: let claude_dir = resolve_claude_dir()?; + ~ hook, settings, setting, json + + 368: /// Backs up before modification, returns true if hook was found and removed + 369: fn remove_hook_from_settings(verbose: u8) -> Result { + 370: let claude_dir = resolve_claude_dir()?; + ~ hook, settings, setting + + +250 more lines + +📄 main.rs [9.8] + 307: /// Remove all RTK artifacts (hook, RTK.md, CLAUDE.md reference, settings.json entry) + 308: #[arg(long)] + ~ hook, settings, setting, json + + 299: /// Auto-patch settings.json without prompting + 300: #[arg(long = "auto-patch", group = "patch")] + ~ settings, setting, json + + +12 more lines + +📄 vitest_cmd.rs [8.8] + 13: #[derive(Debug, Deserialize)] + 14: struct VitestJsonOutput { + 15: #[serde(rename = "testResults")] + ~ json + + 99: /// Extract failures from JSON structure + 100: fn extract_failures_from_json(json: &VitestJsonOutput) -> Vec { + 101: let mut failures = Vec::new(); + ~ json + + +20 more lines + +📄 ccusage.rs [8.7] + 176: fn parse_json(json: &str, granularity: Granularity) -> Result> { + 177: match granularity { + ~ json + + 292: #[test] + 293: fn test_parse_malformed_json() { + 294: let json = r#"{ "monthly": [ { "broken": }"#; + ~ json + + +17 more lines + +📄 pnpm_cmd.rs [8.6] + 519: #[test] + 520: fn test_pnpm_list_parser_json() { + 521: let json = r#"{ + ~ json + + 540: #[test] + 541: fn test_pnpm_outdated_parser_json() { + 542: let json = r#"{ + ~ json + + +16 more lines + +📄 json_cmd.rs [8.4] + 51: /// Useful for piping JSON from other commands (e.g., `gh api`, `curl`). + 52: pub fn filter_json_string(json_str: &str, max_depth: usize) -> Result { + 53: let value: Value = serde_json::from_str(json_str).context("Failed to parse JSON")?; + ~ json + + 2: use anyhow::{Context, Result}; + 3: use serde_json::Value; + 4: use std::fs; + ~ json + + +11 more lines + +📄 parser/mod.rs [8.4] + 133: /// Returns `None` if no valid JSON object found. + 134: pub fn extract_json_object(input: &str) -> Option<&str> { + 135: // Try vitest-specific marker first (most reliable) + ~ json + + 253: #[test] + 254: fn test_extract_json_object_clean() { + 255: let input = r#"{"numTotalTests": 13, "numPassedTests": 13}"#; + ~ json + + +12 more lines + +📄 playwright_cmd.rs [8.4] + 13: #[derive(Debug, Deserialize)] + 14: struct PlaywrightJsonOutput { + 15: #[serde(rename = "stats")] + ~ json + + 287: #[test] + 288: fn test_playwright_parser_json() { + 289: let json = r#"{ + ~ json + + +12 more lines + +... +18F diff --git a/benchmarks/quality_samples/C8_grep.txt b/benchmarks/quality_samples/C8_grep.txt new file mode 100644 index 0000000..e69de29 diff --git a/benchmarks/quality_samples/C8_head_n.txt b/benchmarks/quality_samples/C8_head_n.txt new file mode 100644 index 0000000..e69de29 diff --git a/benchmarks/quality_samples/C8_rtk_grep.txt b/benchmarks/quality_samples/C8_rtk_grep.txt new file mode 100644 index 0000000..3ca55e5 --- /dev/null +++ b/benchmarks/quality_samples/C8_rtk_grep.txt @@ -0,0 +1 @@ +🔍 0 for 'command classification discover' diff --git a/benchmarks/quality_samples/C8_rtk_rgai.txt b/benchmarks/quality_samples/C8_rtk_rgai.txt new file mode 100644 index 0000000..2256671 --- /dev/null +++ b/benchmarks/quality_samples/C8_rtk_rgai.txt @@ -0,0 +1,104 @@ +🧠 38F for 'command classification discover' (scan 55F) + +📄 discover/registry.rs [14.5] + 313: /// Classify a single (already-split) command. + 314: pub fn classify_command(cmd: &str) -> Classification { + 315: let trimmed = cmd.trim(); + ~ command, classification + + 602: fn test_classify_cd_ignored() { + 603: assert_eq!(classify_command("cd /tmp"), Classification::Ignored); + 604: } + ~ command, classification + + +58 more lines + +📄 main.rs [11.6] + 1256: Commands::Discover { + 1257: project, + ~ command, discover + + 77: #[derive(Subcommand)] + 78: enum Commands { + 79: /// List directory contents with token-optimized output (proxy to native ls) + ~ command + + +158 more lines + +📄 discover/mod.rs [11.0] + 8: use provider::{ClaudeProvider, SessionProvider}; + 9: use registry::{category_avg_tokens, classify_command, split_command_chain, Classification}; + 10: use report::{DiscoverReport, SupportedEntry, UnsupportedEntry}; + ~ command, classification + + 125: } + 126: Classification::Unsupported { base_command } => { + 127: let bucket = unsupported_map.entry(base_command).or_insert_with(|| { + ~ command, classification + + +21 more lines + +📄 discover/provider.rs [10.9] + 10: #[derive(Debug)] + 11: pub struct ExtractedCommand { + 12: pub command: String, + ~ command + + 25: pub trait SessionProvider { + 26: fn discover_sessions( + 27: &self, + ~ discover + + +34 more lines + +📄 learn/detector.rs [10.8] + 75: /// Filters out user rejections - requires actual error-indicating content + 76: pub fn is_command_error(is_error: bool, output: &str) -> bool { + 77: if !is_error { + ~ command + + 113: /// Represents a command with its execution result for correction detection + 114: pub struct CommandExecution { + 115: pub command: String, + ~ command + + +111 more lines + +📄 init.rs [10.7] + 733: println!( + 734: " Note: No RTK.md created. Claude won't know about meta commands (gain, discover, proxy)." + 735: ); + ~ command, discover + + 591: /// Creates hooks.PreToolUse structure if missing, preserves existing hooks + 592: fn insert_hook_entry(root: &mut serde_json::Value, hook_command: &str) { + 593: // Ensure root is an object + ~ command + + +65 more lines + +📄 discover/report.rs [10.3] + 45: #[derive(Debug, Serialize)] + 46: pub struct DiscoverReport { + 47: pub sessions_scanned: usize, + ~ discover + + 56: impl DiscoverReport { + 57: pub fn total_saveable_tokens(&self) -> usize { + ~ discover + + +18 more lines + +📄 git.rs [9.9] + 6: #[derive(Debug, Clone)] + 7: pub enum GitCommand { + 8: Diff, + ~ command + + 22: pub fn run(cmd: GitCommand, args: &[String], max_lines: Option, verbose: u8) -> Result<()> { + 23: match cmd { + ~ command + + +44 more lines + +... +30F diff --git a/benchmarks/quality_samples/C9_grep.txt b/benchmarks/quality_samples/C9_grep.txt new file mode 100644 index 0000000..e69de29 diff --git a/benchmarks/quality_samples/C9_head_n.txt b/benchmarks/quality_samples/C9_head_n.txt new file mode 100644 index 0000000..e69de29 diff --git a/benchmarks/quality_samples/C9_rtk_grep.txt b/benchmarks/quality_samples/C9_rtk_grep.txt new file mode 100644 index 0000000..f1d47ec --- /dev/null +++ b/benchmarks/quality_samples/C9_rtk_grep.txt @@ -0,0 +1 @@ +🔍 0 for 'pnpm yarn npm auto detection' diff --git a/benchmarks/quality_samples/C9_rtk_rgai.txt b/benchmarks/quality_samples/C9_rtk_rgai.txt new file mode 100644 index 0000000..0b871f8 --- /dev/null +++ b/benchmarks/quality_samples/C9_rtk_rgai.txt @@ -0,0 +1,104 @@ +🧠 13F for 'pnpm yarn npm auto detection' (scan 55F) + +📄 pnpm_cmd.rs [16.0] + 14: #[derive(Debug, Deserialize)] + 15: struct PnpmListOutput { + 16: #[serde(flatten)] + ~ pnpm, npm + + 20: #[derive(Debug, Deserialize)] + 21: struct PnpmPackage { + 22: version: Option, + ~ pnpm, npm + + +60 more lines + +📄 main.rs [11.8] + 623: #[derive(Subcommand)] + 624: enum PnpmCommands { + 625: /// List installed packages (ultra-dense) + ~ pnpm, npm + + 31: mod playwright_cmd; + 32: mod pnpm_cmd; + 33: mod prettier_cmd; + ~ pnpm, npm + + +29 more lines + +📄 utils.rs [9.8] + 371: let pm = detect_package_manager(); + 372: assert!(["pnpm", "yarn", "npm"].contains(&pm)); + 373: } + ~ pnpm, yarn, npm + + 185: pub fn detect_package_manager() -> &'static str { + 186: if std::path::Path::new("pnpm-lock.yaml").exists() { + 187: "pnpm" + ~ pnpm, npm + + +10 more lines + +📄 npm_cmd.rs [9.7] + 45: /// Filter npm run output - strip boilerplate, progress bars, npm WARN + 46: fn filter_npm_output(output: &str) -> String { + 47: let mut result = Vec::new(); + ~ npm + + 84: #[test] + 85: fn test_filter_npm_output() { + 86: let output = r#" + ~ npm + + +15 more lines + +📄 parser/mod.rs [9.1] + 260: #[test] + 261: fn test_extract_json_object_with_pnpm_prefix() { + 262: let input = r#" + ~ pnpm, npm + + 124: /// Extract a complete JSON object from input that may have non-JSON prefix (pnpm banner, dotenv messages, etc.) + 125: /// + ~ pnpm, npm + + +1 more lines + +📄 vitest_cmd.rs [8.9] + 331: #[test] + 332: fn test_vitest_parser_with_pnpm_prefix() { + 333: let input = r#" + ~ pnpm, npm + + 53: fn parse(input: &str) -> ParseResult { + 54: // Tier 1: Try JSON parsing (with extraction fallback for pnpm/dotenv prefixes) + 55: let json_result = serde_json::from_str::(input).or_else(|first_err| { + ~ pnpm, npm + +📄 init.rs [8.4] + 104: ```bash + 105: rtk pnpm list # Compact dependency tree (70%) + 106: rtk pnpm outdated # Compact outdated packages (80%) + ~ pnpm, npm + + 165: | GitHub | gh pr, gh run, gh issue | 26-87% | + 166: | Package Managers | pnpm, npm, npx | 70-90% | + 167: | Files | ls, read, grep, rgai, find | 60-85% | + ~ pnpm, npm + + +10 more lines + +📄 discover/registry.rs [8.3] + 54: r"^cargo\s+(build|test|clippy|check|fmt)", + 55: r"^pnpm\s+(list|ls|outdated|install)", + 56: r"^npm\s+(run|exec)", + ~ pnpm, npm + + 63: r"^find\s+", + 64: r"^(npx\s+|pnpm\s+)?tsc(\s|$)", + 65: r"^(npx\s+|pnpm\s+)?(eslint|biome|lint)(\s|$)", + ~ pnpm, npm + + +9 more lines + +... +5F diff --git a/benchmarks/quality_samples/D1_grep.txt b/benchmarks/quality_samples/D1_grep.txt new file mode 100644 index 0000000..af959ca --- /dev/null +++ b/benchmarks/quality_samples/D1_grep.txt @@ -0,0 +1,90 @@ +/Users/andrew/Programming/rtk/src/pip_cmd.rs:21: if verbose > 0 && use_uv { +/Users/andrew/Programming/rtk/src/pip_cmd.rs:66: if verbose > 0 { +/Users/andrew/Programming/rtk/src/pip_cmd.rs:101: if verbose > 0 { +/Users/andrew/Programming/rtk/src/pip_cmd.rs:134: if verbose > 0 { +/Users/andrew/Programming/rtk/src/pytest_cmd.rs:42: if verbose > 0 { +/Users/andrew/Programming/rtk/src/ls.rs:94: if verbose > 0 { +/Users/andrew/Programming/rtk/src/local_llm.rs:10: if verbose > 0 { +/Users/andrew/Programming/rtk/src/discover/mod.rs:54: if verbose > 0 { +/Users/andrew/Programming/rtk/src/discover/mod.rs:71: if verbose > 0 { +/Users/andrew/Programming/rtk/src/discover/mod.rs:212: _ => print!("{}", report::format_text(&report, limit, verbose > 0)), +/Users/andrew/Programming/rtk/src/wget_cmd.rs:9: if verbose > 0 { +/Users/andrew/Programming/rtk/src/wget_cmd.rs:57: if verbose > 0 { +/Users/andrew/Programming/rtk/src/npm_cmd.rs:19: if verbose > 0 { +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:41: if verbose > 0 { +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:679: if verbose > 0 { +/Users/andrew/Programming/rtk/src/go_cmd.rs:49: if verbose > 0 { +/Users/andrew/Programming/rtk/src/go_cmd.rs:95: if verbose > 0 { +/Users/andrew/Programming/rtk/src/go_cmd.rs:138: if verbose > 0 { +/Users/andrew/Programming/rtk/src/go_cmd.rs:186: if verbose > 0 { +/Users/andrew/Programming/rtk/src/lint_cmd.rs:57: if verbose > 0 { +/Users/andrew/Programming/rtk/src/curl_cmd.rs:16: if verbose > 0 { +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:54: if verbose > 0 { +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:107: if verbose > 0 { +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:145: if verbose > 0 { +/Users/andrew/Programming/rtk/src/cc_economics.rs:511: if verbose > 0 { +/Users/andrew/Programming/rtk/src/cc_economics.rs:589: if verbose > 0 { +/Users/andrew/Programming/rtk/src/find_cmd.rs:38: if verbose > 0 { +/Users/andrew/Programming/rtk/src/golangci_cmd.rs:54: if verbose > 0 { +/Users/andrew/Programming/rtk/src/golangci_cmd.rs:71: if !stderr.trim().is_empty() && verbose > 0 { +/Users/andrew/Programming/rtk/src/git.rs:90: if verbose > 0 { +/Users/andrew/Programming/rtk/src/git.rs:214: if verbose > 0 { +/Users/andrew/Programming/rtk/src/git.rs:356: if verbose > 0 { +/Users/andrew/Programming/rtk/src/git.rs:540: if verbose > 0 || !stderr.is_empty() { +/Users/andrew/Programming/rtk/src/git.rs:599: if verbose > 0 { +/Users/andrew/Programming/rtk/src/git.rs:657: if verbose > 0 { +/Users/andrew/Programming/rtk/src/git.rs:721: if verbose > 0 { +/Users/andrew/Programming/rtk/src/git.rs:782: if verbose > 0 { +/Users/andrew/Programming/rtk/src/git.rs:867: if verbose > 0 { +/Users/andrew/Programming/rtk/src/git.rs:995: if verbose > 0 { +/Users/andrew/Programming/rtk/src/git.rs:1039: if verbose > 0 { +/Users/andrew/Programming/rtk/src/git.rs:1177: if verbose > 0 { +/Users/andrew/Programming/rtk/src/git.rs:1268: if verbose > 0 { +/Users/andrew/Programming/rtk/src/runner.rs:10: if verbose > 0 { +/Users/andrew/Programming/rtk/src/runner.rs:61: if verbose > 0 { +/Users/andrew/Programming/rtk/src/deps.rs:17: if verbose > 0 { +/Users/andrew/Programming/rtk/src/parser/README.md:102: if verbose > 0 { +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:321: if verbose > 0 { +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:327: if verbose > 0 { +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:373: if verbose > 0 { +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:379: if verbose > 0 { +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:425: if verbose > 0 { +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:495: if verbose > 0 { +/Users/andrew/Programming/rtk/src/tree.rs:86: if verbose > 0 { +/Users/andrew/Programming/rtk/src/log_cmd.rs:13: if verbose > 0 { +/Users/andrew/Programming/rtk/src/ruff_cmd.rs:76: if verbose > 0 { +/Users/andrew/Programming/rtk/src/grep_cmd.rs:19: if verbose > 0 { +/Users/andrew/Programming/rtk/src/json_cmd.rs:12: if verbose > 0 { +/Users/andrew/Programming/rtk/src/json_cmd.rs:34: if verbose > 0 { +/Users/andrew/Programming/rtk/src/read.rs:16: if verbose > 0 { +/Users/andrew/Programming/rtk/src/read.rs:39: if verbose > 0 { +/Users/andrew/Programming/rtk/src/read.rs:83: if verbose > 0 { +/Users/andrew/Programming/rtk/src/read.rs:105: if verbose > 0 { +/Users/andrew/Programming/rtk/src/tsc_cmd.rs:30: if verbose > 0 { +/Users/andrew/Programming/rtk/src/vitest_cmd.rs:246: if verbose > 0 { +/Users/andrew/Programming/rtk/src/vitest_cmd.rs:252: if verbose > 0 { +/Users/andrew/Programming/rtk/src/main.rs:1412: if cli.verbose > 0 { +/Users/andrew/Programming/rtk/src/init.rs:209: if verbose > 0 { +/Users/andrew/Programming/rtk/src/init.rs:216: if verbose > 0 { +/Users/andrew/Programming/rtk/src/init.rs:224: if verbose > 0 { +/Users/andrew/Programming/rtk/src/init.rs:245: if verbose > 0 { +/Users/andrew/Programming/rtk/src/init.rs:252: if verbose > 0 { +/Users/andrew/Programming/rtk/src/init.rs:260: if verbose > 0 { +/Users/andrew/Programming/rtk/src/init.rs:374: if verbose > 0 { +/Users/andrew/Programming/rtk/src/init.rs:403: if verbose > 0 { +/Users/andrew/Programming/rtk/src/init.rs:504: if verbose > 0 { +/Users/andrew/Programming/rtk/src/init.rs:535: if verbose > 0 { +/Users/andrew/Programming/rtk/src/init.rs:773: if verbose > 0 { +/Users/andrew/Programming/rtk/src/init.rs:897: if verbose > 0 { +/Users/andrew/Programming/rtk/src/init.rs:905: if verbose > 0 { +/Users/andrew/Programming/rtk/src/init.rs:923: if verbose > 0 { +/Users/andrew/Programming/rtk/src/diff_cmd.rs:11: if verbose > 0 { +/Users/andrew/Programming/rtk/src/prettier_cmd.rs:15: if verbose > 0 { +/Users/andrew/Programming/rtk/src/next_cmd.rs:31: if verbose > 0 { +/Users/andrew/Programming/rtk/src/env_cmd.rs:10: if verbose > 0 { +/Users/andrew/Programming/rtk/src/container.rs:414: if verbose > 0 { +/Users/andrew/Programming/rtk/src/container.rs:438: if verbose > 0 { +/Users/andrew/Programming/rtk/src/playwright_cmd.rs:231: if verbose > 0 { +/Users/andrew/Programming/rtk/src/playwright_cmd.rs:249: if verbose > 0 { +/Users/andrew/Programming/rtk/src/playwright_cmd.rs:255: if verbose > 0 { +/Users/andrew/Programming/rtk/src/summary.rs:11: if verbose > 0 { diff --git a/benchmarks/quality_samples/D1_head_n.txt b/benchmarks/quality_samples/D1_head_n.txt new file mode 100644 index 0000000..af959ca --- /dev/null +++ b/benchmarks/quality_samples/D1_head_n.txt @@ -0,0 +1,90 @@ +/Users/andrew/Programming/rtk/src/pip_cmd.rs:21: if verbose > 0 && use_uv { +/Users/andrew/Programming/rtk/src/pip_cmd.rs:66: if verbose > 0 { +/Users/andrew/Programming/rtk/src/pip_cmd.rs:101: if verbose > 0 { +/Users/andrew/Programming/rtk/src/pip_cmd.rs:134: if verbose > 0 { +/Users/andrew/Programming/rtk/src/pytest_cmd.rs:42: if verbose > 0 { +/Users/andrew/Programming/rtk/src/ls.rs:94: if verbose > 0 { +/Users/andrew/Programming/rtk/src/local_llm.rs:10: if verbose > 0 { +/Users/andrew/Programming/rtk/src/discover/mod.rs:54: if verbose > 0 { +/Users/andrew/Programming/rtk/src/discover/mod.rs:71: if verbose > 0 { +/Users/andrew/Programming/rtk/src/discover/mod.rs:212: _ => print!("{}", report::format_text(&report, limit, verbose > 0)), +/Users/andrew/Programming/rtk/src/wget_cmd.rs:9: if verbose > 0 { +/Users/andrew/Programming/rtk/src/wget_cmd.rs:57: if verbose > 0 { +/Users/andrew/Programming/rtk/src/npm_cmd.rs:19: if verbose > 0 { +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:41: if verbose > 0 { +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:679: if verbose > 0 { +/Users/andrew/Programming/rtk/src/go_cmd.rs:49: if verbose > 0 { +/Users/andrew/Programming/rtk/src/go_cmd.rs:95: if verbose > 0 { +/Users/andrew/Programming/rtk/src/go_cmd.rs:138: if verbose > 0 { +/Users/andrew/Programming/rtk/src/go_cmd.rs:186: if verbose > 0 { +/Users/andrew/Programming/rtk/src/lint_cmd.rs:57: if verbose > 0 { +/Users/andrew/Programming/rtk/src/curl_cmd.rs:16: if verbose > 0 { +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:54: if verbose > 0 { +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:107: if verbose > 0 { +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:145: if verbose > 0 { +/Users/andrew/Programming/rtk/src/cc_economics.rs:511: if verbose > 0 { +/Users/andrew/Programming/rtk/src/cc_economics.rs:589: if verbose > 0 { +/Users/andrew/Programming/rtk/src/find_cmd.rs:38: if verbose > 0 { +/Users/andrew/Programming/rtk/src/golangci_cmd.rs:54: if verbose > 0 { +/Users/andrew/Programming/rtk/src/golangci_cmd.rs:71: if !stderr.trim().is_empty() && verbose > 0 { +/Users/andrew/Programming/rtk/src/git.rs:90: if verbose > 0 { +/Users/andrew/Programming/rtk/src/git.rs:214: if verbose > 0 { +/Users/andrew/Programming/rtk/src/git.rs:356: if verbose > 0 { +/Users/andrew/Programming/rtk/src/git.rs:540: if verbose > 0 || !stderr.is_empty() { +/Users/andrew/Programming/rtk/src/git.rs:599: if verbose > 0 { +/Users/andrew/Programming/rtk/src/git.rs:657: if verbose > 0 { +/Users/andrew/Programming/rtk/src/git.rs:721: if verbose > 0 { +/Users/andrew/Programming/rtk/src/git.rs:782: if verbose > 0 { +/Users/andrew/Programming/rtk/src/git.rs:867: if verbose > 0 { +/Users/andrew/Programming/rtk/src/git.rs:995: if verbose > 0 { +/Users/andrew/Programming/rtk/src/git.rs:1039: if verbose > 0 { +/Users/andrew/Programming/rtk/src/git.rs:1177: if verbose > 0 { +/Users/andrew/Programming/rtk/src/git.rs:1268: if verbose > 0 { +/Users/andrew/Programming/rtk/src/runner.rs:10: if verbose > 0 { +/Users/andrew/Programming/rtk/src/runner.rs:61: if verbose > 0 { +/Users/andrew/Programming/rtk/src/deps.rs:17: if verbose > 0 { +/Users/andrew/Programming/rtk/src/parser/README.md:102: if verbose > 0 { +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:321: if verbose > 0 { +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:327: if verbose > 0 { +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:373: if verbose > 0 { +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:379: if verbose > 0 { +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:425: if verbose > 0 { +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:495: if verbose > 0 { +/Users/andrew/Programming/rtk/src/tree.rs:86: if verbose > 0 { +/Users/andrew/Programming/rtk/src/log_cmd.rs:13: if verbose > 0 { +/Users/andrew/Programming/rtk/src/ruff_cmd.rs:76: if verbose > 0 { +/Users/andrew/Programming/rtk/src/grep_cmd.rs:19: if verbose > 0 { +/Users/andrew/Programming/rtk/src/json_cmd.rs:12: if verbose > 0 { +/Users/andrew/Programming/rtk/src/json_cmd.rs:34: if verbose > 0 { +/Users/andrew/Programming/rtk/src/read.rs:16: if verbose > 0 { +/Users/andrew/Programming/rtk/src/read.rs:39: if verbose > 0 { +/Users/andrew/Programming/rtk/src/read.rs:83: if verbose > 0 { +/Users/andrew/Programming/rtk/src/read.rs:105: if verbose > 0 { +/Users/andrew/Programming/rtk/src/tsc_cmd.rs:30: if verbose > 0 { +/Users/andrew/Programming/rtk/src/vitest_cmd.rs:246: if verbose > 0 { +/Users/andrew/Programming/rtk/src/vitest_cmd.rs:252: if verbose > 0 { +/Users/andrew/Programming/rtk/src/main.rs:1412: if cli.verbose > 0 { +/Users/andrew/Programming/rtk/src/init.rs:209: if verbose > 0 { +/Users/andrew/Programming/rtk/src/init.rs:216: if verbose > 0 { +/Users/andrew/Programming/rtk/src/init.rs:224: if verbose > 0 { +/Users/andrew/Programming/rtk/src/init.rs:245: if verbose > 0 { +/Users/andrew/Programming/rtk/src/init.rs:252: if verbose > 0 { +/Users/andrew/Programming/rtk/src/init.rs:260: if verbose > 0 { +/Users/andrew/Programming/rtk/src/init.rs:374: if verbose > 0 { +/Users/andrew/Programming/rtk/src/init.rs:403: if verbose > 0 { +/Users/andrew/Programming/rtk/src/init.rs:504: if verbose > 0 { +/Users/andrew/Programming/rtk/src/init.rs:535: if verbose > 0 { +/Users/andrew/Programming/rtk/src/init.rs:773: if verbose > 0 { +/Users/andrew/Programming/rtk/src/init.rs:897: if verbose > 0 { +/Users/andrew/Programming/rtk/src/init.rs:905: if verbose > 0 { +/Users/andrew/Programming/rtk/src/init.rs:923: if verbose > 0 { +/Users/andrew/Programming/rtk/src/diff_cmd.rs:11: if verbose > 0 { +/Users/andrew/Programming/rtk/src/prettier_cmd.rs:15: if verbose > 0 { +/Users/andrew/Programming/rtk/src/next_cmd.rs:31: if verbose > 0 { +/Users/andrew/Programming/rtk/src/env_cmd.rs:10: if verbose > 0 { +/Users/andrew/Programming/rtk/src/container.rs:414: if verbose > 0 { +/Users/andrew/Programming/rtk/src/container.rs:438: if verbose > 0 { +/Users/andrew/Programming/rtk/src/playwright_cmd.rs:231: if verbose > 0 { +/Users/andrew/Programming/rtk/src/playwright_cmd.rs:249: if verbose > 0 { +/Users/andrew/Programming/rtk/src/playwright_cmd.rs:255: if verbose > 0 { +/Users/andrew/Programming/rtk/src/summary.rs:11: if verbose > 0 { diff --git a/benchmarks/quality_samples/D1_rtk_grep.txt b/benchmarks/quality_samples/D1_rtk_grep.txt new file mode 100644 index 0000000..83e6430 --- /dev/null +++ b/benchmarks/quality_samples/D1_rtk_grep.txt @@ -0,0 +1,162 @@ +🔍 90 in 37F: + +📄 /Users/andrew/Programming/rtk/src/cargo_cmd.rs (2): + 41: if verbose > 0 { + 679: if verbose > 0 { + +📄 /Users/andrew/Programming/rtk/src/cc_economics.rs (2): + 511: if verbose > 0 { + 589: if verbose > 0 { + +📄 /Users/andrew/Programming/rtk/src/container.rs (2): + 414: if verbose > 0 { + 438: if verbose > 0 { + +📄 /Users/andrew/Programming/rtk/src/curl_cmd.rs (1): + 16: if verbose > 0 { + +📄 /Users/andrew/Programming/rtk/src/deps.rs (1): + 17: if verbose > 0 { + +📄 /Users/andrew/Programming/rtk/src/diff_cmd.rs (1): + 11: if verbose > 0 { + +📄 /Users/andrew/Programming/rtk/src/discover/mod.rs (3): + 54: if verbose > 0 { + 71: if verbose > 0 { + 212: _ => print!("{}", report::format_text(&report, limit, verbose > 0)), + +📄 /Users/andrew/Programming/rtk/src/env_cmd.rs (1): + 10: if verbose > 0 { + +📄 /Users/andrew/Programming/rtk/src/find_cmd.rs (1): + 38: if verbose > 0 { + +📄 /Users/andrew/Programming/rtk/src/git.rs (13): + 90: if verbose > 0 { + 214: if verbose > 0 { + 356: if verbose > 0 { + 540: if verbose > 0 || !stderr.is_empty() { + 599: if verbose > 0 { + 657: if verbose > 0 { + 721: if verbose > 0 { + 782: if verbose > 0 { + 867: if verbose > 0 { + 995: if verbose > 0 { + +3 + +📄 /Users/andrew/Programming/rtk/src/go_cmd.rs (4): + 49: if verbose > 0 { + 95: if verbose > 0 { + 138: if verbose > 0 { + 186: if verbose > 0 { + +📄 /Users/andrew/Programming/rtk/src/golangci_cmd.rs (2): + 54: if verbose > 0 { + 71: if !stderr.trim().is_empty() && verbose > 0 { + +📄 /Users/andrew/Programming/rtk/src/grep_cmd.rs (1): + 19: if verbose > 0 { + +📄 /Users/andrew/Programming/rtk/src/init.rs (14): + 209: if verbose > 0 { + 216: if verbose > 0 { + 224: if verbose > 0 { + 245: if verbose > 0 { + 252: if verbose > 0 { + 260: if verbose > 0 { + 374: if verbose > 0 { + 403: if verbose > 0 { + 504: if verbose > 0 { + 535: if verbose > 0 { + +4 + +📄 /Users/andrew/Programming/rtk/src/json_cmd.rs (2): + 12: if verbose > 0 { + 34: if verbose > 0 { + +📄 /Users/andrew/Programming/rtk/src/lint_cmd.rs (1): + 57: if verbose > 0 { + +📄 /Users/andrew/Programming/rtk/src/local_llm.rs (1): + 10: if verbose > 0 { + +📄 /Users/andrew/Programming/rtk/src/log_cmd.rs (1): + 13: if verbose > 0 { + +📄 /Users/andrew/Programming/rtk/src/ls.rs (1): + 94: if verbose > 0 { + +📄 /Users/andrew/Programming/rtk/src/main.rs (1): + 1412: if cli.verbose > 0 { + +📄 /Users/andrew/Programming/rtk/src/next_cmd.rs (1): + 31: if verbose > 0 { + +📄 /Users/andrew/Programming/rtk/src/npm_cmd.rs (1): + 19: if verbose > 0 { + +📄 /Users/andrew/Programming/rtk/src/parser/README.md (1): + 102: if verbose > 0 { + +📄 /Users/andrew/Programming/rtk/src/pip_cmd.rs (4): + 21: if verbose > 0 && use_uv { + 66: if verbose > 0 { + 101: if verbose > 0 { + 134: if verbose > 0 { + +📄 /.../src/playwright_cmd.rs (3): + 231: if verbose > 0 { + 249: if verbose > 0 { + 255: if verbose > 0 { + +📄 /Users/andrew/Programming/rtk/src/pnpm_cmd.rs (6): + 321: if verbose > 0 { + 327: if verbose > 0 { + 373: if verbose > 0 { + 379: if verbose > 0 { + 425: if verbose > 0 { + 495: if verbose > 0 { + +📄 /Users/andrew/Programming/rtk/src/prettier_cmd.rs (1): + 15: if verbose > 0 { + +📄 /Users/andrew/Programming/rtk/src/prisma_cmd.rs (3): + 54: if verbose > 0 { + 107: if verbose > 0 { + 145: if verbose > 0 { + +📄 /Users/andrew/Programming/rtk/src/pytest_cmd.rs (1): + 42: if verbose > 0 { + +📄 /Users/andrew/Programming/rtk/src/read.rs (4): + 16: if verbose > 0 { + 39: if verbose > 0 { + 83: if verbose > 0 { + 105: if verbose > 0 { + +📄 /Users/andrew/Programming/rtk/src/ruff_cmd.rs (1): + 76: if verbose > 0 { + +📄 /Users/andrew/Programming/rtk/src/runner.rs (2): + 10: if verbose > 0 { + 61: if verbose > 0 { + +📄 /Users/andrew/Programming/rtk/src/summary.rs (1): + 11: if verbose > 0 { + +📄 /Users/andrew/Programming/rtk/src/tree.rs (1): + 86: if verbose > 0 { + +📄 /Users/andrew/Programming/rtk/src/tsc_cmd.rs (1): + 30: if verbose > 0 { + +📄 /Users/andrew/Programming/rtk/src/vitest_cmd.rs (2): + 246: if verbose > 0 { + 252: if verbose > 0 { + +📄 /Users/andrew/Programming/rtk/src/wget_cmd.rs (2): + 9: if verbose > 0 { + 57: if verbose > 0 { + +... +7 diff --git a/benchmarks/quality_samples/D1_rtk_rgai.txt b/benchmarks/quality_samples/D1_rtk_rgai.txt new file mode 100644 index 0000000..d72e68b --- /dev/null +++ b/benchmarks/quality_samples/D1_rtk_rgai.txt @@ -0,0 +1,97 @@ +🧠 40F for 'verbose > 0' (scan 55F) + +📄 git.rs [14.9] + 90: if verbose > 0 { + 91: eprintln!("Git diff summary:"); + ~ verbose + + 213: if !diff_text.is_empty() { + 214: if verbose > 0 { + 215: println!("\n--- Changes ---"); + ~ verbose + + +37 more lines + +📄 init.rs [14.8] + 208: if existing == REWRITE_HOOK { + 209: if verbose > 0 { + 210: eprintln!("Hook already up to date: {}", hook_path.display()); + ~ verbose + + 215: .with_context(|| format!("Failed to write hook to {}", hook_path.display()))?; + 216: if verbose > 0 { + 217: eprintln!("Updated hook: {}", hook_path.display()); + ~ verbose + + +36 more lines + +📄 cargo_cmd.rs [14.2] + 41: if verbose > 0 { + 42: eprintln!("Running: cargo {} {}", subcommand, args.join(" ")); + ~ verbose + + 679: if verbose > 0 { + 680: eprintln!("cargo passthrough: {:?}", args); + ~ verbose + + +18 more lines + +📄 cc_economics.rs [14.1] + 510: // Verbose mode: legacy metrics + 511: if verbose > 0 { + 512: println!(" Legacy metrics (reference only):"); + ~ verbose + + 589: if verbose > 0 { + 590: // Verbose: include legacy metrics + ~ verbose + + +15 more lines + +📄 container.rs [14.1] + 414: if verbose > 0 { + 415: eprintln!("docker passthrough: {:?}", args); + ~ verbose + + 438: if verbose > 0 { + 439: eprintln!("kubectl passthrough: {:?}", args); + ~ verbose + + +15 more lines + +📄 pnpm_cmd.rs [14.0] + 320: ParseResult::Full(data) => { + 321: if verbose > 0 { + 322: eprintln!("pnpm list (Tier 1: Full JSON parse)"); + ~ verbose + + 326: ParseResult::Degraded(data, warnings) => { + 327: if verbose > 0 { + 328: emit_degradation_warning("pnpm list", &warnings.join(", ")); + ~ verbose + + +14 more lines + +📄 pip_cmd.rs [13.6] + 21: if verbose > 0 && use_uv { + 22: eprintln!("Using uv (pip-compatible)"); + ~ verbose + + 66: if verbose > 0 { + 67: eprintln!("Running: {} pip list --format=json", base_cmd); + ~ verbose + + +9 more lines + +📄 prisma_cmd.rs [13.6] + 54: if verbose > 0 { + 55: eprintln!("Running: prisma generate"); + ~ verbose + + 107: if verbose > 0 { + 108: eprintln!("Running: {}", cmd_name); + ~ verbose + + +8 more lines + +... +32F diff --git a/benchmarks/quality_samples/D2_grep.txt b/benchmarks/quality_samples/D2_grep.txt new file mode 100644 index 0000000..8ae7cf9 --- /dev/null +++ b/benchmarks/quality_samples/D2_grep.txt @@ -0,0 +1,11 @@ +/Users/andrew/Programming/rtk/src/local_llm.rs:281:use anyhow::Result; +/Users/andrew/Programming/rtk/src/learn/report.rs:2:use anyhow::Result; +/Users/andrew/Programming/rtk/src/learn/mod.rs:5:use anyhow::Result; +/Users/andrew/Programming/rtk/src/discover/mod.rs:5:use anyhow::Result; +/Users/andrew/Programming/rtk/src/config.rs:1:use anyhow::Result; +/Users/andrew/Programming/rtk/src/find_cmd.rs:2:use anyhow::Result; +/Users/andrew/Programming/rtk/src/deps.rs:2:use anyhow::Result; +/Users/andrew/Programming/rtk/src/log_cmd.rs:2:use anyhow::Result; +/Users/andrew/Programming/rtk/src/tracking.rs:32:use anyhow::Result; +/Users/andrew/Programming/rtk/src/diff_cmd.rs:3:use anyhow::Result; +/Users/andrew/Programming/rtk/src/env_cmd.rs:2:use anyhow::Result; diff --git a/benchmarks/quality_samples/D2_head_n.txt b/benchmarks/quality_samples/D2_head_n.txt new file mode 100644 index 0000000..8ae7cf9 --- /dev/null +++ b/benchmarks/quality_samples/D2_head_n.txt @@ -0,0 +1,11 @@ +/Users/andrew/Programming/rtk/src/local_llm.rs:281:use anyhow::Result; +/Users/andrew/Programming/rtk/src/learn/report.rs:2:use anyhow::Result; +/Users/andrew/Programming/rtk/src/learn/mod.rs:5:use anyhow::Result; +/Users/andrew/Programming/rtk/src/discover/mod.rs:5:use anyhow::Result; +/Users/andrew/Programming/rtk/src/config.rs:1:use anyhow::Result; +/Users/andrew/Programming/rtk/src/find_cmd.rs:2:use anyhow::Result; +/Users/andrew/Programming/rtk/src/deps.rs:2:use anyhow::Result; +/Users/andrew/Programming/rtk/src/log_cmd.rs:2:use anyhow::Result; +/Users/andrew/Programming/rtk/src/tracking.rs:32:use anyhow::Result; +/Users/andrew/Programming/rtk/src/diff_cmd.rs:3:use anyhow::Result; +/Users/andrew/Programming/rtk/src/env_cmd.rs:2:use anyhow::Result; diff --git a/benchmarks/quality_samples/D2_rtk_grep.txt b/benchmarks/quality_samples/D2_rtk_grep.txt new file mode 100644 index 0000000..5da09e4 --- /dev/null +++ b/benchmarks/quality_samples/D2_rtk_grep.txt @@ -0,0 +1,35 @@ +🔍 11 in 11F: + +📄 /Users/andrew/Programming/rtk/src/config.rs (1): + 1: use anyhow::Result; + +📄 /Users/andrew/Programming/rtk/src/deps.rs (1): + 2: use anyhow::Result; + +📄 /Users/andrew/Programming/rtk/src/diff_cmd.rs (1): + 3: use anyhow::Result; + +📄 /Users/andrew/Programming/rtk/src/discover/mod.rs (1): + 5: use anyhow::Result; + +📄 /Users/andrew/Programming/rtk/src/env_cmd.rs (1): + 2: use anyhow::Result; + +📄 /Users/andrew/Programming/rtk/src/find_cmd.rs (1): + 2: use anyhow::Result; + +📄 /Users/andrew/Programming/rtk/src/learn/mod.rs (1): + 5: use anyhow::Result; + +📄 /Users/andrew/Programming/rtk/src/learn/report.rs (1): + 2: use anyhow::Result; + +📄 /Users/andrew/Programming/rtk/src/local_llm.rs (1): + 281: use anyhow::Result; + +📄 /Users/andrew/Programming/rtk/src/log_cmd.rs (1): + 2: use anyhow::Result; + +📄 /Users/andrew/Programming/rtk/src/tracking.rs (1): + 32: use anyhow::Result; + diff --git a/benchmarks/quality_samples/D2_rtk_rgai.txt b/benchmarks/quality_samples/D2_rtk_rgai.txt new file mode 100644 index 0000000..db475ef --- /dev/null +++ b/benchmarks/quality_samples/D2_rtk_rgai.txt @@ -0,0 +1,102 @@ +🧠 52F for 'anyhow::Result' (scan 55F) + +📄 diff_cmd.rs [16.3] + 2: use crate::utils::truncate; + 3: use anyhow::Result; + 4: use std::fs; + ~ anyhow, result + + 7: /// Ultra-condensed diff - only changed lines, no context + 8: pub fn run(file1: &Path, file2: &Path, verbose: u8) -> Result<()> { + 9: let timer = tracking::TimedExecution::start(); + ~ result + + +44 more lines + +📄 log_cmd.rs [15.9] + 1: use crate::tracking; + 2: use anyhow::Result; + 3: use regex::Regex; + ~ anyhow, result + + 9: /// Filter and deduplicate log output + 10: pub fn run_file(file: &Path, verbose: u8) -> Result<()> { + 11: let timer = tracking::TimedExecution::start(); + ~ result + + +28 more lines + +📄 tracking.rs [15.8] + 32: use anyhow::Result; + 33: use chrono::{DateTime, Utc}; + ~ anyhow, result + + 222: /// ``` + 223: pub fn new() -> Result { + 224: let db_path = get_db_path()?; + ~ result + + +24 more lines + +📄 deps.rs [14.6] + 1: use crate::tracking; + 2: use anyhow::Result; + 3: use regex::Regex; + ~ anyhow, result + + 7: /// Summarize project dependencies + 8: pub fn run(path: &Path, verbose: u8) -> Result<()> { + 9: let timer = tracking::TimedExecution::start(); + ~ result + + +5 more lines + +📄 local_llm.rs [14.5] + 280: let code = r#" + 281: use anyhow::Result; + 282: use std::fs; + ~ anyhow, result + + 1: use anyhow::{Context, Result}; + 2: use regex::Regex; + ~ anyhow, result + + +3 more lines + +📄 config.rs [14.4] + 1: use anyhow::Result; + 2: use serde::{Deserialize, Serialize}; + ~ anyhow, result + + 72: impl Config { + 73: pub fn load() -> Result { + 74: let path = get_config_path()?; + ~ result + + +4 more lines + +📄 find_cmd.rs [14.1] + 1: use crate::tracking; + 2: use anyhow::Result; + 3: use ignore::WalkBuilder; + ~ anyhow, result + + 28: path: &str, + 29: max_results: usize, + 30: file_type: &str, + ~ result + + +13 more lines + +📄 env_cmd.rs [13.6] + 1: use crate::tracking; + 2: use anyhow::Result; + 3: use std::collections::HashSet; + ~ anyhow, result + + 6: /// Show filtered environment variables (hide sensitive data) + 7: pub fn run(filter: Option<&str>, show_all: bool, verbose: u8) -> Result<()> { + 8: let timer = tracking::TimedExecution::start(); + ~ result + +... +44F diff --git a/benchmarks/quality_samples/D3_grep.txt b/benchmarks/quality_samples/D3_grep.txt new file mode 100644 index 0000000..315cedf --- /dev/null +++ b/benchmarks/quality_samples/D3_grep.txt @@ -0,0 +1,47 @@ +/Users/andrew/Programming/rtk/src/pip_cmd.rs:82: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/pip_cmd.rs:117: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/pip_cmd.rs:150: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/pytest_cmd.rs:72: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/ls.rs:88: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/npm_cmd.rs:39: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:63: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:694: std::process::exit(status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/go_cmd.rs:79: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/go_cmd.rs:122: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/go_cmd.rs:165: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/go_cmd.rs:210: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/curl_cmd.rs:31: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/git.rs:63: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/git.rs:148: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/git.rs:184: std::process::exit(summary_output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/git.rs:351: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/git.rs:648: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/git.rs:1283: std::process::exit(status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:510: std::process::exit(status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/tree.rs:80: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/ruff_cmd.rs:108: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/tsc_cmd.rs:54: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/vitest_cmd.rs:268: std::process::exit(output.status.code().unwrap_or(1)) +/Users/andrew/Programming/rtk/src/main.rs:1332: std::process::exit(status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/main.rs:1344: std::process::exit(status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/main.rs:1439: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/prettier_cmd.rs:40: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/next_cmd.rs:51: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/container.rs:429: std::process::exit(status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/container.rs:453: std::process::exit(status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:71: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:162: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:329: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:409: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:464: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:544: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:635: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:719: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:796: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:860: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:898: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:944: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:985: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:1030: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:1078: std::process::exit(status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/playwright_cmd.rs:277: std::process::exit(output.status.code().unwrap_or(1)); diff --git a/benchmarks/quality_samples/D3_head_n.txt b/benchmarks/quality_samples/D3_head_n.txt new file mode 100644 index 0000000..315cedf --- /dev/null +++ b/benchmarks/quality_samples/D3_head_n.txt @@ -0,0 +1,47 @@ +/Users/andrew/Programming/rtk/src/pip_cmd.rs:82: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/pip_cmd.rs:117: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/pip_cmd.rs:150: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/pytest_cmd.rs:72: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/ls.rs:88: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/npm_cmd.rs:39: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:63: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:694: std::process::exit(status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/go_cmd.rs:79: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/go_cmd.rs:122: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/go_cmd.rs:165: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/go_cmd.rs:210: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/curl_cmd.rs:31: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/git.rs:63: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/git.rs:148: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/git.rs:184: std::process::exit(summary_output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/git.rs:351: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/git.rs:648: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/git.rs:1283: std::process::exit(status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:510: std::process::exit(status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/tree.rs:80: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/ruff_cmd.rs:108: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/tsc_cmd.rs:54: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/vitest_cmd.rs:268: std::process::exit(output.status.code().unwrap_or(1)) +/Users/andrew/Programming/rtk/src/main.rs:1332: std::process::exit(status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/main.rs:1344: std::process::exit(status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/main.rs:1439: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/prettier_cmd.rs:40: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/next_cmd.rs:51: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/container.rs:429: std::process::exit(status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/container.rs:453: std::process::exit(status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:71: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:162: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:329: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:409: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:464: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:544: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:635: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:719: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:796: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:860: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:898: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:944: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:985: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:1030: std::process::exit(output.status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:1078: std::process::exit(status.code().unwrap_or(1)); +/Users/andrew/Programming/rtk/src/playwright_cmd.rs:277: std::process::exit(output.status.code().unwrap_or(1)); diff --git a/benchmarks/quality_samples/D3_rtk_grep.txt b/benchmarks/quality_samples/D3_rtk_grep.txt new file mode 100644 index 0000000..895cdd3 --- /dev/null +++ b/benchmarks/quality_samples/D3_rtk_grep.txt @@ -0,0 +1,84 @@ +🔍 47 in 19F: + +📄 /Users/andrew/Programming/rtk/src/cargo_cmd.rs (2): + 63: std::process::exit(output.status.code().unwrap_or(1)); + 694: std::process::exit(status.code().unwrap_or(1)); + +📄 /Users/andrew/Programming/rtk/src/container.rs (2): + 429: std::process::exit(status.code().unwrap_or(1)); + 453: std::process::exit(status.code().unwrap_or(1)); + +📄 /Users/andrew/Programming/rtk/src/curl_cmd.rs (1): + 31: std::process::exit(output.status.code().unwrap_or(1)); + +📄 /Users/andrew/Programming/rtk/src/gh_cmd.rs (15): + 71: std::process::exit(output.status.code().unwrap_or(1)); + 162: std::process::exit(output.status.code().unwrap_or(1)); + 329: std::process::exit(output.status.code().unwrap_or(1)); + 409: std::process::exit(output.status.code().unwrap_or(1)); + 464: std::process::exit(output.status.code().unwrap_or(1)); + 544: std::process::exit(output.status.code().unwrap_or(1)); + 635: std::process::exit(output.status.code().unwrap_or(1)); + 719: std::process::exit(output.status.code().unwrap_or(1)); + 796: std::process::exit(output.status.code().unwrap_or(1)); + 860: std::process::exit(output.status.code().unwrap_or(1)); + +5 + +📄 /Users/andrew/Programming/rtk/src/git.rs (6): + 63: std::process::exit(output.status.code().unwrap_or(1)); + 148: std::process::exit(output.status.code().unwrap_or(1)); + 184: std::process::exit(summary_output.status.code().unwrap_or(1)); + 351: std::process::exit(output.status.code().unwrap_or(1)); + 648: std::process::exit(output.status.code().unwrap_or(1)); + 1283: std::process::exit(status.code().unwrap_or(1)); + +📄 /Users/andrew/Programming/rtk/src/go_cmd.rs (4): + 79: std::process::exit(output.status.code().unwrap_or(1)); + 122: std::process::exit(output.status.code().unwrap_or(1)); + 165: std::process::exit(output.status.code().unwrap_or(1)); + 210: std::process::exit(output.status.code().unwrap_or(1)); + +📄 /Users/andrew/Programming/rtk/src/ls.rs (1): + 88: std::process::exit(output.status.code().unwrap_or(1)); + +📄 /Users/andrew/Programming/rtk/src/main.rs (3): + 1332: std::process::exit(status.code().unwrap_or(1)); + 1344: std::process::exit(status.code().unwrap_or(1)); + 1439: std::process::exit(output.status.code().unwrap_or(1)); + +📄 /Users/andrew/Programming/rtk/src/next_cmd.rs (1): + 51: std::process::exit(output.status.code().unwrap_or(1)); + +📄 /Users/andrew/Programming/rtk/src/npm_cmd.rs (1): + 39: std::process::exit(output.status.code().unwrap_or(1)); + +📄 /Users/andrew/Programming/rtk/src/pip_cmd.rs (3): + 82: std::process::exit(output.status.code().unwrap_or(1)); + 117: std::process::exit(output.status.code().unwrap_or(1)); + 150: std::process::exit(output.status.code().unwrap_or(1)); + +📄 /.../src/playwright_cmd.rs (1): + 277: std::process::exit(output.status.code().unwrap_or(1)); + +📄 /Users/andrew/Programming/rtk/src/pnpm_cmd.rs (1): + 510: std::process::exit(status.code().unwrap_or(1)); + +📄 /Users/andrew/Programming/rtk/src/prettier_cmd.rs (1): + 40: std::process::exit(output.status.code().unwrap_or(1)); + +📄 /Users/andrew/Programming/rtk/src/pytest_cmd.rs (1): + 72: std::process::exit(output.status.code().unwrap_or(1)); + +📄 /Users/andrew/Programming/rtk/src/ruff_cmd.rs (1): + 108: std::process::exit(output.status.code().unwrap_or(1)); + +📄 /Users/andrew/Programming/rtk/src/tree.rs (1): + 80: std::process::exit(output.status.code().unwrap_or(1)); + +📄 /Users/andrew/Programming/rtk/src/tsc_cmd.rs (1): + 54: std::process::exit(output.status.code().unwrap_or(1)); + +📄 /Users/andrew/Programming/rtk/src/vitest_cmd.rs (1): + 268: std::process::exit(output.status.code().unwrap_or(1)) + +... +5 diff --git a/benchmarks/quality_samples/D3_rtk_rgai.txt b/benchmarks/quality_samples/D3_rtk_rgai.txt new file mode 100644 index 0000000..ba3752a --- /dev/null +++ b/benchmarks/quality_samples/D3_rtk_rgai.txt @@ -0,0 +1,106 @@ +🧠 30F for 'process::exit' (scan 55F) + +📄 gh_cmd.rs [20.2] + 70: eprintln!("{}", stderr.trim()); + 71: std::process::exit(output.status.code().unwrap_or(1)); + 72: } + ~ process, proces, exit + + 161: eprintln!("{}", stderr.trim()); + 162: std::process::exit(output.status.code().unwrap_or(1)); + 163: } + ~ process, proces, exit + + +14 more lines + +📄 git.rs [19.6] + 62: eprintln!("{}", stderr); + 63: std::process::exit(output.status.code().unwrap_or(1)); + 64: } + ~ process, proces, exit + + 147: eprintln!("{}", stderr); + 148: std::process::exit(output.status.code().unwrap_or(1)); + 149: } + ~ process, proces, exit + + +6 more lines + +📄 main.rs [19.6] + 1331: if !status.success() { + 1332: std::process::exit(status.code().unwrap_or(1)); + 1333: } + ~ process, proces, exit + + 1343: if !status.success() { + 1344: std::process::exit(status.code().unwrap_or(1)); + 1345: } + ~ process, proces, exit + + +6 more lines + +📄 go_cmd.rs [19.2] + 78: if !output.status.success() { + 79: std::process::exit(output.status.code().unwrap_or(1)); + 80: } + ~ process, proces, exit + + 121: if !output.status.success() { + 122: std::process::exit(output.status.code().unwrap_or(1)); + 123: } + ~ process, proces, exit + + +3 more lines + +📄 pip_cmd.rs [19.0] + 81: if !output.status.success() { + 82: std::process::exit(output.status.code().unwrap_or(1)); + 83: } + ~ process, proces, exit + + 116: if !output.status.success() { + 117: std::process::exit(output.status.code().unwrap_or(1)); + 118: } + ~ process, proces, exit + + +2 more lines + +📄 cargo_cmd.rs [18.8] + 62: if !output.status.success() { + 63: std::process::exit(output.status.code().unwrap_or(1)); + 64: } + ~ process, proces, exit + + 693: if !status.success() { + 694: std::process::exit(status.code().unwrap_or(1)); + 695: } + ~ process, proces, exit + + +1 more lines + +📄 container.rs [18.8] + 428: if !status.success() { + 429: std::process::exit(status.code().unwrap_or(1)); + 430: } + ~ process, proces, exit + + 452: if !status.success() { + 453: std::process::exit(status.code().unwrap_or(1)); + 454: } + ~ process, proces, exit + + +1 more lines + +📄 pytest_cmd.rs [15.5] + 71: if !output.status.success() { + 72: std::process::exit(output.status.code().unwrap_or(1)); + 73: } + ~ process, proces, exit + + 3: use anyhow::{Context, Result}; + 4: use std::process::Command; + ~ process, proces + + +1 more lines + +... +22F diff --git a/benchmarks/quality_samples/D4_grep.txt b/benchmarks/quality_samples/D4_grep.txt new file mode 100644 index 0000000..713a470 --- /dev/null +++ b/benchmarks/quality_samples/D4_grep.txt @@ -0,0 +1,111 @@ +/Users/andrew/Programming/rtk/src/pip_cmd.rs:54: let mut cmd = Command::new(base_cmd); +/Users/andrew/Programming/rtk/src/pip_cmd.rs:89: let mut cmd = Command::new(base_cmd); +/Users/andrew/Programming/rtk/src/pip_cmd.rs:124: let mut cmd = Command::new(base_cmd); +/Users/andrew/Programming/rtk/src/pip_cmd.rs:158: Command::new("which") +/Users/andrew/Programming/rtk/src/pytest_cmd.rs:19: Command::new("pytest") +/Users/andrew/Programming/rtk/src/pytest_cmd.rs:22: let mut c = Command::new("python"); +/Users/andrew/Programming/rtk/src/pytest_cmd.rs:80: Command::new("which") +/Users/andrew/Programming/rtk/src/ls.rs:54: let mut cmd = Command::new("ls"); +/Users/andrew/Programming/rtk/src/wget_cmd.rs:22: let output = Command::new("wget") +/Users/andrew/Programming/rtk/src/wget_cmd.rs:67: let output = Command::new("wget") +/Users/andrew/Programming/rtk/src/npm_cmd.rs:8: let mut cmd = Command::new("npm"); +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:35: let mut cmd = Command::new("cargo"); +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:682: let status = Command::new("cargo") +/Users/andrew/Programming/rtk/src/ccusage.rs:87: Command::new("which") +/Users/andrew/Programming/rtk/src/ccusage.rs:97: return Some(Command::new("ccusage")); +/Users/andrew/Programming/rtk/src/ccusage.rs:101: let npx_check = Command::new("npx") +/Users/andrew/Programming/rtk/src/ccusage.rs:109: let mut cmd = Command::new("npx"); +/Users/andrew/Programming/rtk/src/go_cmd.rs:37: let mut cmd = Command::new("go"); +/Users/andrew/Programming/rtk/src/go_cmd.rs:88: let mut cmd = Command::new("go"); +/Users/andrew/Programming/rtk/src/go_cmd.rs:131: let mut cmd = Command::new("go"); +/Users/andrew/Programming/rtk/src/go_cmd.rs:179: let mut cmd = Command::new("go"); +/Users/andrew/Programming/rtk/src/curl_cmd.rs:9: let mut cmd = Command::new("curl"); +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:29: let prisma_exists = Command::new("which") +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:36: Command::new("prisma") +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:38: let mut c = Command::new("npx"); +/Users/andrew/Programming/rtk/src/golangci_cmd.rs:37: let mut cmd = Command::new("golangci-lint"); +/Users/andrew/Programming/rtk/src/git.rs:52: let mut cmd = Command::new("git"); +/Users/andrew/Programming/rtk/src/git.rs:80: let mut cmd = Command::new("git"); +/Users/andrew/Programming/rtk/src/git.rs:98: let mut diff_cmd = Command::new("git"); +/Users/andrew/Programming/rtk/src/git.rs:139: let mut cmd = Command::new("git"); +/Users/andrew/Programming/rtk/src/git.rs:164: let mut raw_cmd = Command::new("git"); +/Users/andrew/Programming/rtk/src/git.rs:175: let mut summary_cmd = Command::new("git"); +/Users/andrew/Programming/rtk/src/git.rs:190: let mut stat_cmd = Command::new("git"); +/Users/andrew/Programming/rtk/src/git.rs:203: let mut diff_cmd = Command::new("git"); +/Users/andrew/Programming/rtk/src/git.rs:301: let mut cmd = Command::new("git"); +/Users/andrew/Programming/rtk/src/git.rs:531: let output = Command::new("git") +/Users/andrew/Programming/rtk/src/git.rs:560: let raw_output = Command::new("git") +/Users/andrew/Programming/rtk/src/git.rs:566: let output = Command::new("git") +/Users/andrew/Programming/rtk/src/git.rs:585: let mut cmd = Command::new("git"); +/Users/andrew/Programming/rtk/src/git.rs:611: let status_output = Command::new("git") +/Users/andrew/Programming/rtk/src/git.rs:661: let output = Command::new("git") +/Users/andrew/Programming/rtk/src/git.rs:725: let mut cmd = Command::new("git"); +/Users/andrew/Programming/rtk/src/git.rs:786: let mut cmd = Command::new("git"); +/Users/andrew/Programming/rtk/src/git.rs:871: let mut cmd = Command::new("git"); +/Users/andrew/Programming/rtk/src/git.rs:999: let mut cmd = Command::new("git"); +/Users/andrew/Programming/rtk/src/git.rs:1045: let output = Command::new("git") +/Users/andrew/Programming/rtk/src/git.rs:1064: let mut cmd = Command::new("git"); +/Users/andrew/Programming/rtk/src/git.rs:1087: let mut cmd = Command::new("git"); +/Users/andrew/Programming/rtk/src/git.rs:1118: let mut cmd = Command::new("git"); +/Users/andrew/Programming/rtk/src/git.rs:1187: let mut cmd = Command::new("git"); +/Users/andrew/Programming/rtk/src/git.rs:1222: let output = Command::new("git") +/Users/andrew/Programming/rtk/src/git.rs:1271: let status = Command::new("git") +/Users/andrew/Programming/rtk/src/runner.rs:15: Command::new("cmd") +/Users/andrew/Programming/rtk/src/runner.rs:21: Command::new("sh") +/Users/andrew/Programming/rtk/src/runner.rs:66: Command::new("cmd") +/Users/andrew/Programming/rtk/src/runner.rs:72: Command::new("sh") +/Users/andrew/Programming/rtk/src/parser/README.md:18:│ Command::new("vitest").arg("--reporter=json") │ +/Users/andrew/Programming/rtk/src/parser/README.md:87: let mut cmd = Command::new("pnpm"); +/Users/andrew/Programming/rtk/src/parser/README.md:184: let output = Command::new("vitest").output()?; +/Users/andrew/Programming/rtk/src/parser/README.md:194: let output = Command::new("vitest") +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:297: let mut cmd = Command::new("pnpm"); +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:353: let mut cmd = Command::new("pnpm"); +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:414: let mut cmd = Command::new("pnpm"); +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:498: let status = Command::new("pnpm") +/Users/andrew/Programming/rtk/src/tree.rs:47: let tree_check = Command::new("which").arg("tree").output(); +/Users/andrew/Programming/rtk/src/tree.rs:58: let mut cmd = Command::new("tree"); +/Users/andrew/Programming/rtk/src/ruff_cmd.rs:41: let mut cmd = Command::new("ruff"); +/Users/andrew/Programming/rtk/src/grep_cmd.rs:23: let mut rg_cmd = Command::new("rg"); +/Users/andrew/Programming/rtk/src/grep_cmd.rs:36: .or_else(|_| Command::new("grep").args(["-rn", pattern, path]).output()) +/Users/andrew/Programming/rtk/src/tsc_cmd.rs:12: let tsc_exists = Command::new("which") +/Users/andrew/Programming/rtk/src/tsc_cmd.rs:19: Command::new("tsc") +/Users/andrew/Programming/rtk/src/tsc_cmd.rs:21: let mut c = Command::new("npx"); +/Users/andrew/Programming/rtk/src/main.rs:1321: let mut cmd = std::process::Command::new("npx"); +/Users/andrew/Programming/rtk/src/main.rs:1338: let status = std::process::Command::new("npx") +/Users/andrew/Programming/rtk/src/main.rs:1416: let output = Command::new(cmd_name.as_ref()) +/Users/andrew/Programming/rtk/src/next_cmd.rs:11: let next_exists = Command::new("which") +/Users/andrew/Programming/rtk/src/next_cmd.rs:18: Command::new("next") +/Users/andrew/Programming/rtk/src/next_cmd.rs:20: let mut c = Command::new("npx"); +/Users/andrew/Programming/rtk/src/container.rs:30: let raw = Command::new("docker") +/Users/andrew/Programming/rtk/src/container.rs:36: let output = Command::new("docker") +/Users/andrew/Programming/rtk/src/container.rs:87: let raw = Command::new("docker") +/Users/andrew/Programming/rtk/src/container.rs:93: let output = Command::new("docker") +/Users/andrew/Programming/rtk/src/container.rs:163: let output = Command::new("docker") +/Users/andrew/Programming/rtk/src/container.rs:187: let mut cmd = Command::new("kubectl"); +/Users/andrew/Programming/rtk/src/container.rs:288: let mut cmd = Command::new("kubectl"); +/Users/andrew/Programming/rtk/src/container.rs:368: let mut cmd = Command::new("kubectl"); +/Users/andrew/Programming/rtk/src/container.rs:417: let status = Command::new("docker") +/Users/andrew/Programming/rtk/src/container.rs:441: let status = Command::new("kubectl") +/Users/andrew/Programming/rtk/src/utils.rs:71: let output = Command::new(cmd) +/Users/andrew/Programming/rtk/src/utils.rs:198: let tool_exists = Command::new("which") +/Users/andrew/Programming/rtk/src/utils.rs:205: Command::new(tool) +/Users/andrew/Programming/rtk/src/utils.rs:210: let mut c = Command::new("pnpm"); +/Users/andrew/Programming/rtk/src/utils.rs:215: let mut c = Command::new("yarn"); +/Users/andrew/Programming/rtk/src/utils.rs:220: let mut c = Command::new("npx"); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:51: let mut cmd = Command::new("gh"); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:141: let mut cmd = Command::new("gh"); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:314: let mut cmd = Command::new("gh"); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:394: let mut cmd = Command::new("gh"); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:450: let mut cmd = Command::new("gh"); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:523: let mut cmd = Command::new("gh"); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:615: let mut cmd = Command::new("gh"); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:704: let mut cmd = Command::new("gh"); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:777: let mut cmd = Command::new("gh"); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:847: let mut cmd = Command::new("gh"); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:885: let mut cmd = Command::new("gh"); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:931: let mut cmd = Command::new("gh"); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:965: let mut cmd = Command::new("gh"); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:1017: let mut cmd = Command::new("gh"); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:1061: let mut command = Command::new(cmd); +/Users/andrew/Programming/rtk/src/summary.rs:16: Command::new("cmd") +/Users/andrew/Programming/rtk/src/summary.rs:22: Command::new("sh") diff --git a/benchmarks/quality_samples/D4_head_n.txt b/benchmarks/quality_samples/D4_head_n.txt new file mode 100644 index 0000000..d38b101 --- /dev/null +++ b/benchmarks/quality_samples/D4_head_n.txt @@ -0,0 +1,100 @@ +/Users/andrew/Programming/rtk/src/pip_cmd.rs:54: let mut cmd = Command::new(base_cmd); +/Users/andrew/Programming/rtk/src/pip_cmd.rs:89: let mut cmd = Command::new(base_cmd); +/Users/andrew/Programming/rtk/src/pip_cmd.rs:124: let mut cmd = Command::new(base_cmd); +/Users/andrew/Programming/rtk/src/pip_cmd.rs:158: Command::new("which") +/Users/andrew/Programming/rtk/src/pytest_cmd.rs:19: Command::new("pytest") +/Users/andrew/Programming/rtk/src/pytest_cmd.rs:22: let mut c = Command::new("python"); +/Users/andrew/Programming/rtk/src/pytest_cmd.rs:80: Command::new("which") +/Users/andrew/Programming/rtk/src/ls.rs:54: let mut cmd = Command::new("ls"); +/Users/andrew/Programming/rtk/src/wget_cmd.rs:22: let output = Command::new("wget") +/Users/andrew/Programming/rtk/src/wget_cmd.rs:67: let output = Command::new("wget") +/Users/andrew/Programming/rtk/src/npm_cmd.rs:8: let mut cmd = Command::new("npm"); +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:35: let mut cmd = Command::new("cargo"); +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:682: let status = Command::new("cargo") +/Users/andrew/Programming/rtk/src/ccusage.rs:87: Command::new("which") +/Users/andrew/Programming/rtk/src/ccusage.rs:97: return Some(Command::new("ccusage")); +/Users/andrew/Programming/rtk/src/ccusage.rs:101: let npx_check = Command::new("npx") +/Users/andrew/Programming/rtk/src/ccusage.rs:109: let mut cmd = Command::new("npx"); +/Users/andrew/Programming/rtk/src/go_cmd.rs:37: let mut cmd = Command::new("go"); +/Users/andrew/Programming/rtk/src/go_cmd.rs:88: let mut cmd = Command::new("go"); +/Users/andrew/Programming/rtk/src/go_cmd.rs:131: let mut cmd = Command::new("go"); +/Users/andrew/Programming/rtk/src/go_cmd.rs:179: let mut cmd = Command::new("go"); +/Users/andrew/Programming/rtk/src/curl_cmd.rs:9: let mut cmd = Command::new("curl"); +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:29: let prisma_exists = Command::new("which") +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:36: Command::new("prisma") +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:38: let mut c = Command::new("npx"); +/Users/andrew/Programming/rtk/src/golangci_cmd.rs:37: let mut cmd = Command::new("golangci-lint"); +/Users/andrew/Programming/rtk/src/git.rs:52: let mut cmd = Command::new("git"); +/Users/andrew/Programming/rtk/src/git.rs:80: let mut cmd = Command::new("git"); +/Users/andrew/Programming/rtk/src/git.rs:98: let mut diff_cmd = Command::new("git"); +/Users/andrew/Programming/rtk/src/git.rs:139: let mut cmd = Command::new("git"); +/Users/andrew/Programming/rtk/src/git.rs:164: let mut raw_cmd = Command::new("git"); +/Users/andrew/Programming/rtk/src/git.rs:175: let mut summary_cmd = Command::new("git"); +/Users/andrew/Programming/rtk/src/git.rs:190: let mut stat_cmd = Command::new("git"); +/Users/andrew/Programming/rtk/src/git.rs:203: let mut diff_cmd = Command::new("git"); +/Users/andrew/Programming/rtk/src/git.rs:301: let mut cmd = Command::new("git"); +/Users/andrew/Programming/rtk/src/git.rs:531: let output = Command::new("git") +/Users/andrew/Programming/rtk/src/git.rs:560: let raw_output = Command::new("git") +/Users/andrew/Programming/rtk/src/git.rs:566: let output = Command::new("git") +/Users/andrew/Programming/rtk/src/git.rs:585: let mut cmd = Command::new("git"); +/Users/andrew/Programming/rtk/src/git.rs:611: let status_output = Command::new("git") +/Users/andrew/Programming/rtk/src/git.rs:661: let output = Command::new("git") +/Users/andrew/Programming/rtk/src/git.rs:725: let mut cmd = Command::new("git"); +/Users/andrew/Programming/rtk/src/git.rs:786: let mut cmd = Command::new("git"); +/Users/andrew/Programming/rtk/src/git.rs:871: let mut cmd = Command::new("git"); +/Users/andrew/Programming/rtk/src/git.rs:999: let mut cmd = Command::new("git"); +/Users/andrew/Programming/rtk/src/git.rs:1045: let output = Command::new("git") +/Users/andrew/Programming/rtk/src/git.rs:1064: let mut cmd = Command::new("git"); +/Users/andrew/Programming/rtk/src/git.rs:1087: let mut cmd = Command::new("git"); +/Users/andrew/Programming/rtk/src/git.rs:1118: let mut cmd = Command::new("git"); +/Users/andrew/Programming/rtk/src/git.rs:1187: let mut cmd = Command::new("git"); +/Users/andrew/Programming/rtk/src/git.rs:1222: let output = Command::new("git") +/Users/andrew/Programming/rtk/src/git.rs:1271: let status = Command::new("git") +/Users/andrew/Programming/rtk/src/runner.rs:15: Command::new("cmd") +/Users/andrew/Programming/rtk/src/runner.rs:21: Command::new("sh") +/Users/andrew/Programming/rtk/src/runner.rs:66: Command::new("cmd") +/Users/andrew/Programming/rtk/src/runner.rs:72: Command::new("sh") +/Users/andrew/Programming/rtk/src/parser/README.md:18:│ Command::new("vitest").arg("--reporter=json") │ +/Users/andrew/Programming/rtk/src/parser/README.md:87: let mut cmd = Command::new("pnpm"); +/Users/andrew/Programming/rtk/src/parser/README.md:184: let output = Command::new("vitest").output()?; +/Users/andrew/Programming/rtk/src/parser/README.md:194: let output = Command::new("vitest") +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:297: let mut cmd = Command::new("pnpm"); +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:353: let mut cmd = Command::new("pnpm"); +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:414: let mut cmd = Command::new("pnpm"); +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:498: let status = Command::new("pnpm") +/Users/andrew/Programming/rtk/src/tree.rs:47: let tree_check = Command::new("which").arg("tree").output(); +/Users/andrew/Programming/rtk/src/tree.rs:58: let mut cmd = Command::new("tree"); +/Users/andrew/Programming/rtk/src/ruff_cmd.rs:41: let mut cmd = Command::new("ruff"); +/Users/andrew/Programming/rtk/src/grep_cmd.rs:23: let mut rg_cmd = Command::new("rg"); +/Users/andrew/Programming/rtk/src/grep_cmd.rs:36: .or_else(|_| Command::new("grep").args(["-rn", pattern, path]).output()) +/Users/andrew/Programming/rtk/src/tsc_cmd.rs:12: let tsc_exists = Command::new("which") +/Users/andrew/Programming/rtk/src/tsc_cmd.rs:19: Command::new("tsc") +/Users/andrew/Programming/rtk/src/tsc_cmd.rs:21: let mut c = Command::new("npx"); +/Users/andrew/Programming/rtk/src/main.rs:1321: let mut cmd = std::process::Command::new("npx"); +/Users/andrew/Programming/rtk/src/main.rs:1338: let status = std::process::Command::new("npx") +/Users/andrew/Programming/rtk/src/main.rs:1416: let output = Command::new(cmd_name.as_ref()) +/Users/andrew/Programming/rtk/src/next_cmd.rs:11: let next_exists = Command::new("which") +/Users/andrew/Programming/rtk/src/next_cmd.rs:18: Command::new("next") +/Users/andrew/Programming/rtk/src/next_cmd.rs:20: let mut c = Command::new("npx"); +/Users/andrew/Programming/rtk/src/container.rs:30: let raw = Command::new("docker") +/Users/andrew/Programming/rtk/src/container.rs:36: let output = Command::new("docker") +/Users/andrew/Programming/rtk/src/container.rs:87: let raw = Command::new("docker") +/Users/andrew/Programming/rtk/src/container.rs:93: let output = Command::new("docker") +/Users/andrew/Programming/rtk/src/container.rs:163: let output = Command::new("docker") +/Users/andrew/Programming/rtk/src/container.rs:187: let mut cmd = Command::new("kubectl"); +/Users/andrew/Programming/rtk/src/container.rs:288: let mut cmd = Command::new("kubectl"); +/Users/andrew/Programming/rtk/src/container.rs:368: let mut cmd = Command::new("kubectl"); +/Users/andrew/Programming/rtk/src/container.rs:417: let status = Command::new("docker") +/Users/andrew/Programming/rtk/src/container.rs:441: let status = Command::new("kubectl") +/Users/andrew/Programming/rtk/src/utils.rs:71: let output = Command::new(cmd) +/Users/andrew/Programming/rtk/src/utils.rs:198: let tool_exists = Command::new("which") +/Users/andrew/Programming/rtk/src/utils.rs:205: Command::new(tool) +/Users/andrew/Programming/rtk/src/utils.rs:210: let mut c = Command::new("pnpm"); +/Users/andrew/Programming/rtk/src/utils.rs:215: let mut c = Command::new("yarn"); +/Users/andrew/Programming/rtk/src/utils.rs:220: let mut c = Command::new("npx"); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:51: let mut cmd = Command::new("gh"); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:141: let mut cmd = Command::new("gh"); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:314: let mut cmd = Command::new("gh"); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:394: let mut cmd = Command::new("gh"); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:450: let mut cmd = Command::new("gh"); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:523: let mut cmd = Command::new("gh"); diff --git a/benchmarks/quality_samples/D4_rtk_grep.txt b/benchmarks/quality_samples/D4_rtk_grep.txt new file mode 100644 index 0000000..352f63f --- /dev/null +++ b/benchmarks/quality_samples/D4_rtk_grep.txt @@ -0,0 +1,145 @@ +🔍 111 in 25F: + +📄 /Users/andrew/Programming/rtk/src/cargo_cmd.rs (2): + 35: let mut cmd = Command::new("cargo"); + 682: let status = Command::new("cargo") + +📄 /Users/andrew/Programming/rtk/src/ccusage.rs (4): + 87: Command::new("which") + 97: return Some(Command::new("ccusage")); + 101: let npx_check = Command::new("npx") + 109: let mut cmd = Command::new("npx"); + +📄 /Users/andrew/Programming/rtk/src/container.rs (10): + 30: let raw = Command::new("docker") + 36: let output = Command::new("docker") + 87: let raw = Command::new("docker") + 93: let output = Command::new("docker") + 163: let output = Command::new("docker") + 187: let mut cmd = Command::new("kubectl"); + 288: let mut cmd = Command::new("kubectl"); + 368: let mut cmd = Command::new("kubectl"); + 417: let status = Command::new("docker") + 441: let status = Command::new("kubectl") + +📄 /Users/andrew/Programming/rtk/src/curl_cmd.rs (1): + 9: let mut cmd = Command::new("curl"); + +📄 /Users/andrew/Programming/rtk/src/gh_cmd.rs (15): + 51: let mut cmd = Command::new("gh"); + 141: let mut cmd = Command::new("gh"); + 314: let mut cmd = Command::new("gh"); + 394: let mut cmd = Command::new("gh"); + 450: let mut cmd = Command::new("gh"); + 523: let mut cmd = Command::new("gh"); + 615: let mut cmd = Command::new("gh"); + 704: let mut cmd = Command::new("gh"); + 777: let mut cmd = Command::new("gh"); + 847: let mut cmd = Command::new("gh"); + +5 + +📄 /Users/andrew/Programming/rtk/src/git.rs (26): + 52: let mut cmd = Command::new("git"); + 80: let mut cmd = Command::new("git"); + 98: let mut diff_cmd = Command::new("git"); + 139: let mut cmd = Command::new("git"); + 164: let mut raw_cmd = Command::new("git"); + 175: let mut summary_cmd = Command::new("git"); + 190: let mut stat_cmd = Command::new("git"); + 203: let mut diff_cmd = Command::new("git"); + 301: let mut cmd = Command::new("git"); + 531: let output = Command::new("git") + +16 + +📄 /Users/andrew/Programming/rtk/src/go_cmd.rs (4): + 37: let mut cmd = Command::new("go"); + 88: let mut cmd = Command::new("go"); + 131: let mut cmd = Command::new("go"); + 179: let mut cmd = Command::new("go"); + +📄 /Users/andrew/Programming/rtk/src/golangci_cmd.rs (1): + 37: let mut cmd = Command::new("golangci-lint"); + +📄 /Users/andrew/Programming/rtk/src/grep_cmd.rs (2): + 23: let mut rg_cmd = Command::new("rg"); + 36: .or_else(|_| Command::new("grep").args(["-rn", pattern, path]).output()) + +📄 /Users/andrew/Programming/rtk/src/ls.rs (1): + 54: let mut cmd = Command::new("ls"); + +📄 /Users/andrew/Programming/rtk/src/main.rs (3): + 1321: let mut cmd = std::process::Command::new("npx"); + 1338: let status = std::process::Command::new("npx") + 1416: let output = Command::new(cmd_name.as_ref()) + +📄 /Users/andrew/Programming/rtk/src/next_cmd.rs (3): + 11: let next_exists = Command::new("which") + 18: Command::new("next") + 20: let mut c = Command::new("npx"); + +📄 /Users/andrew/Programming/rtk/src/npm_cmd.rs (1): + 8: let mut cmd = Command::new("npm"); + +📄 /Users/andrew/Programming/rtk/src/parser/README.md (4): + 18: │ Command::new("vitest").arg("--reporter=json") │ + 87: let mut cmd = Command::new("pnpm"); + 184: let output = Command::new("vitest").output()?; + 194: let output = Command::new("vitest") + +📄 /Users/andrew/Programming/rtk/src/pip_cmd.rs (4): + 54: let mut cmd = Command::new(base_cmd); + 89: let mut cmd = Command::new(base_cmd); + 124: let mut cmd = Command::new(base_cmd); + 158: Command::new("which") + +📄 /Users/andrew/Programming/rtk/src/pnpm_cmd.rs (4): + 297: let mut cmd = Command::new("pnpm"); + 353: let mut cmd = Command::new("pnpm"); + 414: let mut cmd = Command::new("pnpm"); + 498: let status = Command::new("pnpm") + +📄 /Users/andrew/Programming/rtk/src/prisma_cmd.rs (3): + 29: let prisma_exists = Command::new("which") + 36: Command::new("prisma") + 38: let mut c = Command::new("npx"); + +📄 /Users/andrew/Programming/rtk/src/pytest_cmd.rs (3): + 19: Command::new("pytest") + 22: let mut c = Command::new("python"); + 80: Command::new("which") + +📄 /Users/andrew/Programming/rtk/src/ruff_cmd.rs (1): + 41: let mut cmd = Command::new("ruff"); + +📄 /Users/andrew/Programming/rtk/src/runner.rs (4): + 15: Command::new("cmd") + 21: Command::new("sh") + 66: Command::new("cmd") + 72: Command::new("sh") + +📄 /Users/andrew/Programming/rtk/src/summary.rs (2): + 16: Command::new("cmd") + 22: Command::new("sh") + +📄 /Users/andrew/Programming/rtk/src/tree.rs (2): + 47: let tree_check = Command::new("which").arg("tree").output(); + 58: let mut cmd = Command::new("tree"); + +📄 /Users/andrew/Programming/rtk/src/tsc_cmd.rs (3): + 12: let tsc_exists = Command::new("which") + 19: Command::new("tsc") + 21: let mut c = Command::new("npx"); + +📄 /Users/andrew/Programming/rtk/src/utils.rs (6): + 71: let output = Command::new(cmd) + 198: let tool_exists = Command::new("which") + 205: Command::new(tool) + 210: let mut c = Command::new("pnpm"); + 215: let mut c = Command::new("yarn"); + 220: let mut c = Command::new("npx"); + +📄 /Users/andrew/Programming/rtk/src/wget_cmd.rs (2): + 22: let output = Command::new("wget") + 67: let output = Command::new("wget") + +... +21 diff --git a/benchmarks/quality_samples/D4_rtk_rgai.txt b/benchmarks/quality_samples/D4_rtk_rgai.txt new file mode 100644 index 0000000..4ce4b99 --- /dev/null +++ b/benchmarks/quality_samples/D4_rtk_rgai.txt @@ -0,0 +1,102 @@ +🧠 50F for 'Command::new' (scan 55F) + +📄 main.rs [20.0] + 1320: let timer = tracking::TimedExecution::start(); + 1321: let mut cmd = std::process::Command::new("npx"); + 1322: for arg in &args { + ~ command, new + + 1337: let timer = tracking::TimedExecution::start(); + 1338: let status = std::process::Command::new("npx") + 1339: .arg("prisma") + ~ command, new + + +159 more lines + +📄 git.rs [19.1] + 51: // User wants stat or explicitly no compacting - pass through directly + 52: let mut cmd = Command::new("git"); + 53: cmd.arg("diff"); + ~ command, new + + 79: // Default RTK behavior: stat first, then compacted diff + 80: let mut cmd = Command::new("git"); + 81: cmd.arg("diff").arg("--stat"); + ~ command, new + + +64 more lines + +📄 runner.rs [18.8] + 14: let output = if cfg!(target_os = "windows") { + 15: Command::new("cmd") + 16: .args(["/C", command]) + ~ command, new + + 20: } else { + 21: Command::new("sh") + 22: .args(["-c", command]) + ~ command, new + + +43 more lines + +📄 gh_cmd.rs [18.6] + 51: let mut cmd = Command::new("gh"); + 52: cmd.args([ + ~ command, new + + 141: let mut cmd = Command::new("gh"); + 142: cmd.args([ + ~ command, new + + +38 more lines + +📄 cargo_cmd.rs [18.5] + 35: let mut cmd = Command::new("cargo"); + 36: cmd.arg(subcommand); + ~ command, new + + 681: } + 682: let status = Command::new("cargo") + 683: .args(args) + ~ command, new + + +34 more lines + +📄 prisma_cmd.rs [18.5] + 28: fn create_prisma_command() -> Command { + 29: let prisma_exists = Command::new("which") + 30: .arg("prisma") + ~ command, new + + 35: if prisma_exists { + 36: Command::new("prisma") + 37: } else { + ~ command, new + + +33 more lines + +📄 summary.rs [18.1] + 15: let output = if cfg!(target_os = "windows") { + 16: Command::new("cmd") + 17: .args(["/C", command]) + ~ command, new + + 21: } else { + 22: Command::new("sh") + 23: .args(["-c", command]) + ~ command, new + + +21 more lines + +📄 go_cmd.rs [18.0] + 37: let mut cmd = Command::new("go"); + 38: cmd.arg("test"); + ~ command, new + + 88: let mut cmd = Command::new("go"); + 89: cmd.arg("build"); + ~ command, new + + +18 more lines + +... +42F diff --git a/benchmarks/quality_samples/D5_grep.txt b/benchmarks/quality_samples/D5_grep.txt new file mode 100644 index 0000000..2650bf7 --- /dev/null +++ b/benchmarks/quality_samples/D5_grep.txt @@ -0,0 +1,157 @@ +/Users/andrew/Programming/rtk/src/pip_cmd.rs:74: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/pip_cmd.rs:75: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/pip_cmd.rs:109: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/pip_cmd.rs:110: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/pip_cmd.rs:142: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/pip_cmd.rs:143: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/pytest_cmd.rs:50: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/pytest_cmd.rs:51: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/ls.rs:86: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/ls.rs:91: let raw = String::from_utf8_lossy(&output.stdout).to_string(); +/Users/andrew/Programming/rtk/src/wget_cmd.rs:27: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/wget_cmd.rs:28: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/wget_cmd.rs:73: let content = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/wget_cmd.rs:105: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/npm_cmd.rs:24: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/npm_cmd.rs:25: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:48: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:49: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/ccusage.rs:158: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/ccusage.rs:167: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/go_cmd.rs:57: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/go_cmd.rs:58: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/go_cmd.rs:103: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/go_cmd.rs:104: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/go_cmd.rs:146: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/go_cmd.rs:147: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/go_cmd.rs:194: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/go_cmd.rs:195: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/lint_cmd.rs:65: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/lint_cmd.rs:76: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/lint_cmd.rs:77: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/curl_cmd.rs:21: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/curl_cmd.rs:22: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:63: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:67: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:68: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:114: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:118: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:119: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:152: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:156: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:157: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/golangci_cmd.rs:62: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/golangci_cmd.rs:63: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/git.rs:61: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/git.rs:66: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/git.rs:88: let stat_stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/git.rs:105: let diff_stdout = String::from_utf8_lossy(&diff_output.stdout); +/Users/andrew/Programming/rtk/src/git.rs:146: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/git.rs:150: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/git.rs:171: .map(|o| String::from_utf8_lossy(&o.stdout).to_string()) +/Users/andrew/Programming/rtk/src/git.rs:182: let stderr = String::from_utf8_lossy(&summary_output.stderr); +/Users/andrew/Programming/rtk/src/git.rs:186: let summary = String::from_utf8_lossy(&summary_output.stdout); +/Users/andrew/Programming/rtk/src/git.rs:196: let stat_stdout = String::from_utf8_lossy(&stat_output.stdout); +/Users/andrew/Programming/rtk/src/git.rs:209: let diff_stdout = String::from_utf8_lossy(&diff_output.stdout); +/Users/andrew/Programming/rtk/src/git.rs:348: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/git.rs:354: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/git.rs:537: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/git.rs:538: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/git.rs:563: .map(|o| String::from_utf8_lossy(&o.stdout).to_string()) +/Users/andrew/Programming/rtk/src/git.rs:571: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/git.rs:605: String::from_utf8_lossy(&output.stdout), +/Users/andrew/Programming/rtk/src/git.rs:606: String::from_utf8_lossy(&output.stderr) +/Users/andrew/Programming/rtk/src/git.rs:616: let stat = String::from_utf8_lossy(&status_output.stdout); +/Users/andrew/Programming/rtk/src/git.rs:638: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/git.rs:639: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/git.rs:666: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/git.rs:667: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/git.rs:733: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/git.rs:734: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/git.rs:794: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/git.rs:795: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/git.rs:884: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/git.rs:885: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/git.rs:922: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/git.rs:1006: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/git.rs:1007: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/git.rs:1049: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/git.rs:1070: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/git.rs:1093: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/git.rs:1094: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/git.rs:1124: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/git.rs:1125: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/git.rs:1193: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/git.rs:1194: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/git.rs:1227: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/runner.rs:29: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/runner.rs:30: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/runner.rs:80: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/runner.rs:81: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/parser/README.md:92: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:309: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:313: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:363: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:364: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:430: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:431: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/tree.rs:78: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/tree.rs:83: let raw = String::from_utf8_lossy(&output.stdout).to_string(); +/Users/andrew/Programming/rtk/src/ruff_cmd.rs:84: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/ruff_cmd.rs:85: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/grep_cmd.rs:39: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/tsc_cmd.rs:38: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/tsc_cmd.rs:39: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/vitest_cmd.rs:236: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/vitest_cmd.rs:237: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/main.rs:1421: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/main.rs:1422: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/prettier_cmd.rs:23: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/prettier_cmd.rs:24: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/next_cmd.rs:39: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/next_cmd.rs:40: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/container.rs:33: .map(|o| String::from_utf8_lossy(&o.stdout).to_string()) +/Users/andrew/Programming/rtk/src/container.rs:45: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/container.rs:90: .map(|o| String::from_utf8_lossy(&o.stdout).to_string()) +/Users/andrew/Programming/rtk/src/container.rs:98: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/container.rs:168: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/container.rs:169: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/container.rs:194: let raw = String::from_utf8_lossy(&output.stdout).to_string(); +/Users/andrew/Programming/rtk/src/container.rs:295: let raw = String::from_utf8_lossy(&output.stdout).to_string(); +/Users/andrew/Programming/rtk/src/container.rs:375: let raw = String::from_utf8_lossy(&output.stdout).to_string(); +/Users/andrew/Programming/rtk/src/utils.rs:76: let stdout = String::from_utf8_lossy(&output.stdout).to_string(); +/Users/andrew/Programming/rtk/src/utils.rs:77: let stderr = String::from_utf8_lossy(&output.stderr).to_string(); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:65: let raw = String::from_utf8_lossy(&output.stdout).to_string(); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:68: let stderr = String::from_utf8_lossy(&output.stderr).to_string(); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:151: let raw = String::from_utf8_lossy(&output.stdout).to_string(); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:154: let stderr = String::from_utf8_lossy(&output.stderr).to_string(); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:318: let raw = String::from_utf8_lossy(&output.stdout).to_string(); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:321: let stderr = String::from_utf8_lossy(&output.stderr).to_string(); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:332: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:403: let raw = String::from_utf8_lossy(&output.stdout).to_string(); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:406: let stderr = String::from_utf8_lossy(&output.stderr).to_string(); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:458: let raw = String::from_utf8_lossy(&output.stdout).to_string(); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:461: let stderr = String::from_utf8_lossy(&output.stderr).to_string(); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:533: let raw = String::from_utf8_lossy(&output.stdout).to_string(); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:536: let stderr = String::from_utf8_lossy(&output.stderr).to_string(); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:629: let raw = String::from_utf8_lossy(&output.stdout).to_string(); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:632: let stderr = String::from_utf8_lossy(&output.stderr).to_string(); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:708: let raw = String::from_utf8_lossy(&output.stdout).to_string(); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:711: let stderr = String::from_utf8_lossy(&output.stderr).to_string(); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:723: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:790: let raw = String::from_utf8_lossy(&output.stdout).to_string(); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:793: let stderr = String::from_utf8_lossy(&output.stderr).to_string(); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:854: let stdout = String::from_utf8_lossy(&output.stdout).to_string(); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:855: let stderr = String::from_utf8_lossy(&output.stderr).to_string(); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:892: let stdout = String::from_utf8_lossy(&output.stdout).to_string(); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:893: let stderr = String::from_utf8_lossy(&output.stderr).to_string(); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:938: let raw = String::from_utf8_lossy(&output.stdout).to_string(); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:941: let stderr = String::from_utf8_lossy(&output.stderr).to_string(); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:974: let stdout = String::from_utf8_lossy(&output.stdout).to_string(); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:977: let stderr = String::from_utf8_lossy(&output.stderr).to_string(); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:1024: let raw = String::from_utf8_lossy(&output.stdout).to_string(); +/Users/andrew/Programming/rtk/src/gh_cmd.rs:1027: let stderr = String::from_utf8_lossy(&output.stderr).to_string(); +/Users/andrew/Programming/rtk/src/playwright_cmd.rs:239: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/playwright_cmd.rs:240: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/summary.rs:30: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/summary.rs:31: let stderr = String::from_utf8_lossy(&output.stderr); diff --git a/benchmarks/quality_samples/D5_head_n.txt b/benchmarks/quality_samples/D5_head_n.txt new file mode 100644 index 0000000..9256074 --- /dev/null +++ b/benchmarks/quality_samples/D5_head_n.txt @@ -0,0 +1,100 @@ +/Users/andrew/Programming/rtk/src/pip_cmd.rs:74: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/pip_cmd.rs:75: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/pip_cmd.rs:109: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/pip_cmd.rs:110: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/pip_cmd.rs:142: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/pip_cmd.rs:143: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/pytest_cmd.rs:50: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/pytest_cmd.rs:51: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/ls.rs:86: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/ls.rs:91: let raw = String::from_utf8_lossy(&output.stdout).to_string(); +/Users/andrew/Programming/rtk/src/wget_cmd.rs:27: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/wget_cmd.rs:28: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/wget_cmd.rs:73: let content = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/wget_cmd.rs:105: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/npm_cmd.rs:24: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/npm_cmd.rs:25: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:48: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:49: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/ccusage.rs:158: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/ccusage.rs:167: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/go_cmd.rs:57: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/go_cmd.rs:58: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/go_cmd.rs:103: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/go_cmd.rs:104: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/go_cmd.rs:146: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/go_cmd.rs:147: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/go_cmd.rs:194: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/go_cmd.rs:195: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/lint_cmd.rs:65: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/lint_cmd.rs:76: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/lint_cmd.rs:77: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/curl_cmd.rs:21: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/curl_cmd.rs:22: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:63: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:67: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:68: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:114: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:118: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:119: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:152: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:156: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:157: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/golangci_cmd.rs:62: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/golangci_cmd.rs:63: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/git.rs:61: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/git.rs:66: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/git.rs:88: let stat_stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/git.rs:105: let diff_stdout = String::from_utf8_lossy(&diff_output.stdout); +/Users/andrew/Programming/rtk/src/git.rs:146: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/git.rs:150: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/git.rs:171: .map(|o| String::from_utf8_lossy(&o.stdout).to_string()) +/Users/andrew/Programming/rtk/src/git.rs:182: let stderr = String::from_utf8_lossy(&summary_output.stderr); +/Users/andrew/Programming/rtk/src/git.rs:186: let summary = String::from_utf8_lossy(&summary_output.stdout); +/Users/andrew/Programming/rtk/src/git.rs:196: let stat_stdout = String::from_utf8_lossy(&stat_output.stdout); +/Users/andrew/Programming/rtk/src/git.rs:209: let diff_stdout = String::from_utf8_lossy(&diff_output.stdout); +/Users/andrew/Programming/rtk/src/git.rs:348: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/git.rs:354: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/git.rs:537: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/git.rs:538: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/git.rs:563: .map(|o| String::from_utf8_lossy(&o.stdout).to_string()) +/Users/andrew/Programming/rtk/src/git.rs:571: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/git.rs:605: String::from_utf8_lossy(&output.stdout), +/Users/andrew/Programming/rtk/src/git.rs:606: String::from_utf8_lossy(&output.stderr) +/Users/andrew/Programming/rtk/src/git.rs:616: let stat = String::from_utf8_lossy(&status_output.stdout); +/Users/andrew/Programming/rtk/src/git.rs:638: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/git.rs:639: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/git.rs:666: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/git.rs:667: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/git.rs:733: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/git.rs:734: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/git.rs:794: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/git.rs:795: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/git.rs:884: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/git.rs:885: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/git.rs:922: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/git.rs:1006: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/git.rs:1007: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/git.rs:1049: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/git.rs:1070: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/git.rs:1093: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/git.rs:1094: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/git.rs:1124: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/git.rs:1125: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/git.rs:1193: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/git.rs:1194: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/git.rs:1227: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/runner.rs:29: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/runner.rs:30: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/runner.rs:80: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/runner.rs:81: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/parser/README.md:92: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:309: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:313: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:363: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:364: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:430: let stdout = String::from_utf8_lossy(&output.stdout); +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:431: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/tree.rs:78: let stderr = String::from_utf8_lossy(&output.stderr); +/Users/andrew/Programming/rtk/src/tree.rs:83: let raw = String::from_utf8_lossy(&output.stdout).to_string(); +/Users/andrew/Programming/rtk/src/ruff_cmd.rs:84: let stdout = String::from_utf8_lossy(&output.stdout); diff --git a/benchmarks/quality_samples/D5_rtk_grep.txt b/benchmarks/quality_samples/D5_rtk_grep.txt new file mode 100644 index 0000000..680d99e --- /dev/null +++ b/benchmarks/quality_samples/D5_rtk_grep.txt @@ -0,0 +1,168 @@ +🔍 157 in 29F: + +📄 /Users/andrew/Programming/rtk/src/cargo_cmd.rs (2): + 48: let stdout = String::from_utf8_lossy(&output.stdout); + 49: let stderr = String::from_utf8_lossy(&output.stderr); + +📄 /Users/andrew/Programming/rtk/src/ccusage.rs (2): + 158: let stderr = String::from_utf8_lossy(&output.stderr); + 167: let stdout = String::from_utf8_lossy(&output.stdout); + +📄 /Users/andrew/Programming/rtk/src/container.rs (9): + 33: .map(|o| String::from_utf8_lossy(&o.stdout).to_string()) + 45: let stdout = String::from_utf8_lossy(&output.stdout); + 90: .map(|o| String::from_utf8_lossy(&o.stdout).to_string()) + 98: let stdout = String::from_utf8_lossy(&output.stdout); + 168: let stdout = String::from_utf8_lossy(&output.stdout); + 169: let stderr = String::from_utf8_lossy(&output.stderr); + 194: let raw = String::from_utf8_lossy(&output.stdout).to_string(); + 295: let raw = String::from_utf8_lossy(&output.stdout).to_string(); + 375: let raw = String::from_utf8_lossy(&output.stdout).to_string(); + +📄 /Users/andrew/Programming/rtk/src/curl_cmd.rs (2): + 21: let stdout = String::from_utf8_lossy(&output.stdout); + 22: let stderr = String::from_utf8_lossy(&output.stderr); + +📄 /Users/andrew/Programming/rtk/src/gh_cmd.rs (30): + 65: let raw = String::from_utf8_lossy(&output.stdout).to_string(); + 68: let stderr = String::from_utf8_lossy(&output.stderr).to_string(); + 151: let raw = String::from_utf8_lossy(&output.stdout).to_string(); + 154: let stderr = String::from_utf8_lossy(&output.stderr).to_string(); + 318: let raw = String::from_utf8_lossy(&output.stdout).to_string(); + 321: let stderr = String::from_utf8_lossy(&output.stderr).to_string(); + 332: let stdout = String::from_utf8_lossy(&output.stdout); + 403: let raw = String::from_utf8_lossy(&output.stdout).to_string(); + 406: let stderr = String::from_utf8_lossy(&output.stderr).to_string(); + 458: let raw = String::from_utf8_lossy(&output.stdout).to_string(); + +20 + +📄 /Users/andrew/Programming/rtk/src/git.rs (42): + 61: let stderr = String::from_utf8_lossy(&output.stderr); + 66: let stdout = String::from_utf8_lossy(&output.stdout); + 88: let stat_stdout = String::from_utf8_lossy(&output.stdout); + 105: let diff_stdout = String::from_utf8_lossy(&diff_output.stdout); + 146: let stderr = String::from_utf8_lossy(&output.stderr); + 150: let stdout = String::from_utf8_lossy(&output.stdout); + 171: .map(|o| String::from_utf8_lossy(&o.stdout).to_string()) + 182: let stderr = String::from_utf8_lossy(&summary_output.stderr); + 186: let summary = String::from_utf8_lossy(&summary_output.stdout); + 196: let stat_stdout = String::from_utf8_lossy(&stat_output.stdout); + +32 + +📄 /Users/andrew/Programming/rtk/src/go_cmd.rs (8): + 57: let stdout = String::from_utf8_lossy(&output.stdout); + 58: let stderr = String::from_utf8_lossy(&output.stderr); + 103: let stdout = String::from_utf8_lossy(&output.stdout); + 104: let stderr = String::from_utf8_lossy(&output.stderr); + 146: let stdout = String::from_utf8_lossy(&output.stdout); + 147: let stderr = String::from_utf8_lossy(&output.stderr); + 194: let stdout = String::from_utf8_lossy(&output.stdout); + 195: let stderr = String::from_utf8_lossy(&output.stderr); + +📄 /Users/andrew/Programming/rtk/src/golangci_cmd.rs (2): + 62: let stdout = String::from_utf8_lossy(&output.stdout); + 63: let stderr = String::from_utf8_lossy(&output.stderr); + +📄 /Users/andrew/Programming/rtk/src/grep_cmd.rs (1): + 39: let stdout = String::from_utf8_lossy(&output.stdout); + +📄 /Users/andrew/Programming/rtk/src/lint_cmd.rs (3): + 65: let stderr = String::from_utf8_lossy(&output.stderr); + 76: let stdout = String::from_utf8_lossy(&output.stdout); + 77: let stderr = String::from_utf8_lossy(&output.stderr); + +📄 /Users/andrew/Programming/rtk/src/ls.rs (2): + 86: let stderr = String::from_utf8_lossy(&output.stderr); + 91: let raw = String::from_utf8_lossy(&output.stdout).to_string(); + +📄 /Users/andrew/Programming/rtk/src/main.rs (2): + 1421: let stdout = String::from_utf8_lossy(&output.stdout); + 1422: let stderr = String::from_utf8_lossy(&output.stderr); + +📄 /Users/andrew/Programming/rtk/src/next_cmd.rs (2): + 39: let stdout = String::from_utf8_lossy(&output.stdout); + 40: let stderr = String::from_utf8_lossy(&output.stderr); + +📄 /Users/andrew/Programming/rtk/src/npm_cmd.rs (2): + 24: let stdout = String::from_utf8_lossy(&output.stdout); + 25: let stderr = String::from_utf8_lossy(&output.stderr); + +📄 /Users/andrew/Programming/rtk/src/parser/README.md (1): + 92: let stdout = String::from_utf8_lossy(&output.stdout); + +📄 /Users/andrew/Programming/rtk/src/pip_cmd.rs (6): + 74: let stdout = String::from_utf8_lossy(&output.stdout); + 75: let stderr = String::from_utf8_lossy(&output.stderr); + 109: let stdout = String::from_utf8_lossy(&output.stdout); + 110: let stderr = String::from_utf8_lossy(&output.stderr); + 142: let stdout = String::from_utf8_lossy(&output.stdout); + 143: let stderr = String::from_utf8_lossy(&output.stderr); + +📄 /.../src/playwright_cmd.rs (2): + 239: let stdout = String::from_utf8_lossy(&output.stdout); + 240: let stderr = String::from_utf8_lossy(&output.stderr); + +📄 /Users/andrew/Programming/rtk/src/pnpm_cmd.rs (6): + 309: let stderr = String::from_utf8_lossy(&output.stderr); + 313: let stdout = String::from_utf8_lossy(&output.stdout); + 363: let stdout = String::from_utf8_lossy(&output.stdout); + 364: let stderr = String::from_utf8_lossy(&output.stderr); + 430: let stdout = String::from_utf8_lossy(&output.stdout); + 431: let stderr = String::from_utf8_lossy(&output.stderr); + +📄 /Users/andrew/Programming/rtk/src/prettier_cmd.rs (2): + 23: let stdout = String::from_utf8_lossy(&output.stdout); + 24: let stderr = String::from_utf8_lossy(&output.stderr); + +📄 /Users/andrew/Programming/rtk/src/prisma_cmd.rs (9): + 63: let stderr = String::from_utf8_lossy(&output.stderr); + 67: let stdout = String::from_utf8_lossy(&output.stdout); + 68: let stderr = String::from_utf8_lossy(&output.stderr); + 114: let stderr = String::from_utf8_lossy(&output.stderr); + 118: let stdout = String::from_utf8_lossy(&output.stdout); + 119: let stderr = String::from_utf8_lossy(&output.stderr); + 152: let stderr = String::from_utf8_lossy(&output.stderr); + 156: let stdout = String::from_utf8_lossy(&output.stdout); + 157: let stderr = String::from_utf8_lossy(&output.stderr); + +📄 /Users/andrew/Programming/rtk/src/pytest_cmd.rs (2): + 50: let stdout = String::from_utf8_lossy(&output.stdout); + 51: let stderr = String::from_utf8_lossy(&output.stderr); + +📄 /Users/andrew/Programming/rtk/src/ruff_cmd.rs (2): + 84: let stdout = String::from_utf8_lossy(&output.stdout); + 85: let stderr = String::from_utf8_lossy(&output.stderr); + +📄 /Users/andrew/Programming/rtk/src/runner.rs (4): + 29: let stdout = String::from_utf8_lossy(&output.stdout); + 30: let stderr = String::from_utf8_lossy(&output.stderr); + 80: let stdout = String::from_utf8_lossy(&output.stdout); + 81: let stderr = String::from_utf8_lossy(&output.stderr); + +📄 /Users/andrew/Programming/rtk/src/summary.rs (2): + 30: let stdout = String::from_utf8_lossy(&output.stdout); + 31: let stderr = String::from_utf8_lossy(&output.stderr); + +📄 /Users/andrew/Programming/rtk/src/tree.rs (2): + 78: let stderr = String::from_utf8_lossy(&output.stderr); + 83: let raw = String::from_utf8_lossy(&output.stdout).to_string(); + +📄 /Users/andrew/Programming/rtk/src/tsc_cmd.rs (2): + 38: let stdout = String::from_utf8_lossy(&output.stdout); + 39: let stderr = String::from_utf8_lossy(&output.stderr); + +📄 /Users/andrew/Programming/rtk/src/utils.rs (2): + 76: let stdout = String::from_utf8_lossy(&output.stdout).to_string(); + 77: let stderr = String::from_utf8_lossy(&output.stderr).to_string(); + +📄 /Users/andrew/Programming/rtk/src/vitest_cmd.rs (2): + 236: let stdout = String::from_utf8_lossy(&output.stdout); + 237: let stderr = String::from_utf8_lossy(&output.stderr); + +📄 /Users/andrew/Programming/rtk/src/wget_cmd.rs (4): + 27: let stderr = String::from_utf8_lossy(&output.stderr); + 28: let stdout = String::from_utf8_lossy(&output.stdout); + 73: let content = String::from_utf8_lossy(&output.stdout); + 105: let stderr = String::from_utf8_lossy(&output.stderr); + +... +52 diff --git a/benchmarks/quality_samples/D5_rtk_rgai.txt b/benchmarks/quality_samples/D5_rtk_rgai.txt new file mode 100644 index 0000000..515952d --- /dev/null +++ b/benchmarks/quality_samples/D5_rtk_rgai.txt @@ -0,0 +1,94 @@ +🧠 29F for 'from_utf8_lossy' (scan 55F) + +📄 git.rs [14.9] + 60: if !output.status.success() { + 61: let stderr = String::from_utf8_lossy(&output.stderr); + 62: eprintln!("{}", stderr); + ~ from_utf8_lossy + + 66: let stdout = String::from_utf8_lossy(&output.stdout); + 67: println!("{}", stdout.trim()); + ~ from_utf8_lossy + + +40 more lines + +📄 gh_cmd.rs [14.6] + 64: let output = cmd.output().context("Failed to run gh pr list")?; + 65: let raw = String::from_utf8_lossy(&output.stdout).to_string(); + ~ from_utf8_lossy + + 150: let output = cmd.output().context("Failed to run gh pr view")?; + 151: let raw = String::from_utf8_lossy(&output.stdout).to_string(); + ~ from_utf8_lossy + + +28 more lines + +📄 container.rs [13.5] + 32: .output() + 33: .map(|o| String::from_utf8_lossy(&o.stdout).to_string()) + 34: .unwrap_or_default(); + ~ from_utf8_lossy + + 45: let stdout = String::from_utf8_lossy(&output.stdout); + 46: let mut rtk = String::new(); + ~ from_utf8_lossy + + +7 more lines + +📄 prisma_cmd.rs [13.5] + 62: if !output.status.success() { + 63: let stderr = String::from_utf8_lossy(&output.stderr); + 64: anyhow::bail!("prisma generate failed: {}", stderr); + ~ from_utf8_lossy + + 67: let stdout = String::from_utf8_lossy(&output.stdout); + 68: let stderr = String::from_utf8_lossy(&output.stderr); + ~ from_utf8_lossy + + +7 more lines + +📄 go_cmd.rs [13.4] + 57: let stdout = String::from_utf8_lossy(&output.stdout); + 58: let stderr = String::from_utf8_lossy(&output.stderr); + ~ from_utf8_lossy + + 103: let stdout = String::from_utf8_lossy(&output.stdout); + 104: let stderr = String::from_utf8_lossy(&output.stderr); + ~ from_utf8_lossy + + +6 more lines + +📄 pip_cmd.rs [13.1] + 74: let stdout = String::from_utf8_lossy(&output.stdout); + 75: let stderr = String::from_utf8_lossy(&output.stderr); + ~ from_utf8_lossy + + 109: let stdout = String::from_utf8_lossy(&output.stdout); + 110: let stderr = String::from_utf8_lossy(&output.stderr); + ~ from_utf8_lossy + + +4 more lines + +📄 pnpm_cmd.rs [13.1] + 308: if !output.status.success() { + 309: let stderr = String::from_utf8_lossy(&output.stderr); + 310: anyhow::bail!("pnpm list failed: {}", stderr); + ~ from_utf8_lossy + + 313: let stdout = String::from_utf8_lossy(&output.stdout); + ~ from_utf8_lossy + + +4 more lines + +📄 runner.rs [12.8] + 29: let stdout = String::from_utf8_lossy(&output.stdout); + 30: let stderr = String::from_utf8_lossy(&output.stderr); + ~ from_utf8_lossy + + 80: let stdout = String::from_utf8_lossy(&output.stdout); + 81: let stderr = String::from_utf8_lossy(&output.stderr); + ~ from_utf8_lossy + + +2 more lines + +... +21F diff --git a/benchmarks/quality_samples/E1_grep.txt b/benchmarks/quality_samples/E1_grep.txt new file mode 100644 index 0000000..b944a44 --- /dev/null +++ b/benchmarks/quality_samples/E1_grep.txt @@ -0,0 +1,178 @@ +/Users/andrew/Programming/rtk/src/pip_cmd.rs:163: .and_then(|o| String::from_utf8(o.stdout).ok()) +/Users/andrew/Programming/rtk/src/pytest_cmd.rs:85: .and_then(|o| String::from_utf8(o.stdout).ok()) +/Users/andrew/Programming/rtk/src/ls.rs:52: // Build ls -la + any extra flags the user passed (e.g. -R) +/Users/andrew/Programming/rtk/src/ls.rs:53: // Strip -l, -a, -h (we handle all of these ourselves) +/Users/andrew/Programming/rtk/src/local_llm.rs:19: .and_then(|e| e.to_str()) +/Users/andrew/Programming/rtk/src/local_llm.rs:62: (!functions.is_empty()).then(|| format!("{} fn", functions.len())), +/Users/andrew/Programming/rtk/src/local_llm.rs:63: (!structs.is_empty()).then(|| format!("{} struct", structs.len())), +/Users/andrew/Programming/rtk/src/local_llm.rs:64: (!traits.is_empty()).then(|| format!("{} trait", traits.len())), +/Users/andrew/Programming/rtk/src/learn/detector.rs:12: Other(String), +/Users/andrew/Programming/rtk/src/learn/detector.rs:24: ErrorType::Other(s) => s, +/Users/andrew/Programming/rtk/src/learn/detector.rs:58: r"(?i)(no such file or directory|cannot find the path|file not found)" +/Users/andrew/Programming/rtk/src/learn/detector.rs:109: ErrorType::Other("General Error".to_string()) +/Users/andrew/Programming/rtk/src/learn/detector.rs:194: matches!(error_type, ErrorType::CommandNotFound | ErrorType::Other(_)) +/Users/andrew/Programming/rtk/src/learn/detector.rs:282:/// Extract the specific token that changed between wrong and right commands +/Users/andrew/Programming/rtk/src/learn/detector.rs:293: // Return the most distinctive change +/Users/andrew/Programming/rtk/src/learn/detector.rs:320: // For each group, keep the best confidence example +/Users/andrew/Programming/rtk/src/learn/detector.rs:421: ErrorType::Other(_) +/Users/andrew/Programming/rtk/src/learn/detector.rs:544: // Let me adjust: they have same base "cat" but different args +/Users/andrew/Programming/rtk/src/learn/mod.rs:37: println!("No Claude Code sessions found in the last {} days.", since); +/Users/andrew/Programming/rtk/src/discover/registry.rs:287: "then\n", +/Users/andrew/Programming/rtk/src/discover/registry.rs:288: "then ", +/Users/andrew/Programming/rtk/src/discover/registry.rs:339: // Fast check with RegexSet — take the last (most specific) match +/Users/andrew/Programming/rtk/src/discover/registry.rs:391:/// Extract the base command (first word, or first two if it looks like a subcommand pattern). +/Users/andrew/Programming/rtk/src/discover/registry.rs:399: // If the second token looks like a subcommand (no leading -) +/Users/andrew/Programming/rtk/src/discover/registry.rs:404: .and_then(|i| { +/Users/andrew/Programming/rtk/src/discover/registry.rs:421:/// For pipes `|`, only keep the first command. +/Users/andrew/Programming/rtk/src/discover/registry.rs:625: other => panic!("expected Unsupported, got {:?}", other), +/Users/andrew/Programming/rtk/src/discover/registry.rs:719: // except Other has a matching pattern in the registry +/Users/andrew/Programming/rtk/src/discover/registry.rs:724: other => panic!("cargo {subcmd} should be Supported, got {other:?}"), +/Users/andrew/Programming/rtk/src/discover/registry.rs:739: other => panic!("git {subcmd} should be Supported, got {other:?}"), +/Users/andrew/Programming/rtk/src/discover/provider.rs:18: /// Whether the tool_result indicated an error +/Users/andrew/Programming/rtk/src/discover/provider.rs:20: /// Chronological sequence index within the session +/Users/andrew/Programming/rtk/src/discover/provider.rs:37: /// Get the base directory for Claude Code projects. +/Users/andrew/Programming/rtk/src/discover/provider.rs:84: let dir_name = path.file_name().and_then(|n| n.to_str()).unwrap_or(""); +/Users/andrew/Programming/rtk/src/discover/provider.rs:90: // Walk the project directory recursively (catches subagents/) +/Users/andrew/Programming/rtk/src/discover/provider.rs:97: if file_path.extension().and_then(|e| e.to_str()) != Some("jsonl") { +/Users/andrew/Programming/rtk/src/discover/provider.rs:126: .and_then(|s| s.to_str()) +/Users/andrew/Programming/rtk/src/discover/provider.rs:130: // First pass: collect all tool_use Bash commands with their IDs and sequence +/Users/andrew/Programming/rtk/src/discover/provider.rs:153: let entry_type = entry.get("type").and_then(|t| t.as_str()).unwrap_or(""); +/Users/andrew/Programming/rtk/src/discover/provider.rs:159: entry.pointer("/message/content").and_then(|c| c.as_array()) +/Users/andrew/Programming/rtk/src/discover/provider.rs:162: if block.get("type").and_then(|t| t.as_str()) == Some("tool_use") +/Users/andrew/Programming/rtk/src/discover/provider.rs:163: && block.get("name").and_then(|n| n.as_str()) == Some("Bash") +/Users/andrew/Programming/rtk/src/discover/provider.rs:166: block.get("id").and_then(|i| i.as_str()), +/Users/andrew/Programming/rtk/src/discover/provider.rs:167: block.pointer("/input/command").and_then(|c| c.as_str()), +/Users/andrew/Programming/rtk/src/discover/provider.rs:183: entry.pointer("/message/content").and_then(|c| c.as_array()) +/Users/andrew/Programming/rtk/src/discover/provider.rs:186: if block.get("type").and_then(|t| t.as_str()) == Some("tool_result") { +/Users/andrew/Programming/rtk/src/discover/provider.rs:187: if let Some(id) = block.get("tool_use_id").and_then(|i| i.as_str()) +/Users/andrew/Programming/rtk/src/discover/provider.rs:191: block.get("content").and_then(|c| c.as_str()).unwrap_or(""); +/Users/andrew/Programming/rtk/src/discover/provider.rs:196: .and_then(|e| e.as_bool()) +/Users/andrew/Programming/rtk/src/discover/provider.rs:216: // Match tool_uses with their results +/Users/andrew/Programming/rtk/src/discover/report.rs:8: /// Works via external_subcommand passthrough, no filtering (e.g., cargo fmt → Other) +/Users/andrew/Programming/rtk/src/discover/report.rs:177: // UTF-8 safe truncation: collect chars up to max-2, then add ".." +/Users/andrew/Programming/rtk/src/discover/mod.rs:19: // For display: the most common raw command +/Users/andrew/Programming/rtk/src/discover/mod.rs:118: // Track the display name with status +/Users/andrew/Programming/rtk/src/discover/mod.rs:140: // Otherwise just skip +/Users/andrew/Programming/rtk/src/discover/mod.rs:151: // Pick the most common command as the display name +/Users/andrew/Programming/rtk/src/discover/mod.rs:218:/// Extract the subcommand from a command string (second word). +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:419: /// Merge another test result into this one +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:420: fn merge(&mut self, other: &Self) { +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:421: self.passed += other.passed; +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:422: self.failed += other.failed; +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:423: self.ignored += other.ignored; +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:424: self.measured += other.measured; +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:425: self.filtered_out += other.filtered_out; +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:426: self.suites += other.suites; +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:427: self.duration_secs += other.duration_secs; +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:428: self.has_duration = self.has_duration && other.has_duration; +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:628: // No bracket: use the message itself as the rule +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:836: // Should NOT aggregate when there are failures +/Users/andrew/Programming/rtk/src/ccusage.rs:94:/// Build the ccusage command, falling back to npx if binary not in PATH +/Users/andrew/Programming/rtk/src/ccusage.rs:122:/// Fetch usage data from ccusage for the last 90 days +/Users/andrew/Programming/rtk/src/go_cmd.rs:171:pub fn run_other(args: &[OsString], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/lint_cmd.rs:31: // Detect if eslint or other linter (ignore paths containing / or .) +/Users/andrew/Programming/rtk/src/lint_cmd.rs:46: // Add user arguments (skip first if it was the linter name) +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:27:/// Create a Command that will run prisma (tries global first, then npx) +/Users/andrew/Programming/rtk/src/cc_economics.rs:506: println!(" RTK compresses CLI outputs before they enter Claude's context."); +/Users/andrew/Programming/rtk/src/find_cmd.rs:249: // run() converts "." to "*" internally, test the logic +/Users/andrew/Programming/rtk/src/git.rs:79: // Default RTK behavior: stat first, then compacted diff +/Users/andrew/Programming/rtk/src/git.rs:314: // Apply RTK defaults only if user didn't specify them +/Users/andrew/Programming/rtk/src/git.rs:328: .and_then(|arg| arg[1..].parse::().ok()) +/Users/andrew/Programming/rtk/src/git.rs:817: .and_then(|n| n.parse().ok()) +/Users/andrew/Programming/rtk/src/git.rs:823: .and_then(|n| n.parse().ok()) +/Users/andrew/Programming/rtk/src/git.rs:829: .and_then(|n| n.parse().ok()) +/Users/andrew/Programming/rtk/src/git.rs:1422: // Compile-time verification that the function exists with correct signature +/Users/andrew/Programming/rtk/src/git.rs:1427: let output = "abc1234 This is a commit message (2 days ago) \ndef5678 Another commit (1 week ago) \n"; +/Users/andrew/Programming/rtk/src/git.rs:1489: // The line has 30 Thai chars (90 bytes) + other text, so > 80 bytes +/Users/andrew/Programming/rtk/src/deps.rs:132: if let Some(name) = json.get("name").and_then(|v| v.as_str()) { +/Users/andrew/Programming/rtk/src/deps.rs:133: let version = json.get("version").and_then(|v| v.as_str()).unwrap_or("?"); +/Users/andrew/Programming/rtk/src/deps.rs:136: if let Some(deps) = json.get("dependencies").and_then(|v| v.as_object()) { +/Users/andrew/Programming/rtk/src/deps.rs:150: if let Some(dev_deps) = json.get("devDependencies").and_then(|v| v.as_object()) { +/Users/andrew/Programming/rtk/src/parser/error.rs:35: Other(#[from] anyhow::Error), +/Users/andrew/Programming/rtk/src/parser/mod.rs:31: /// Unwrap the parsed data, panicking on Passthrough +/Users/andrew/Programming/rtk/src/parser/mod.rs:40: /// Get the tier level (1 = Full, 2 = Degraded, 3 = Passthrough) +/Users/andrew/Programming/rtk/src/parser/mod.rs:54: /// Map the parsed data while preserving tier +/Users/andrew/Programming/rtk/src/parser/mod.rs:179: let end_pos = start_pos + i + 1; // +1 to include the `}` +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:571: // Compile-time verification that the function exists with correct signature +/Users/andrew/Programming/rtk/src/tree.rs:3://! This module proxies to the native `tree` command and filters the output +/Users/andrew/Programming/rtk/src/tree.rs:115: // Skip the final summary line (e.g., "5 directories, 23 files") +/Users/andrew/Programming/rtk/src/tree.rs:120: // Skip empty lines at the end +/Users/andrew/Programming/rtk/src/log_cmd.rs:48:/// For use by other modules +/Users/andrew/Programming/rtk/src/ruff_cmd.rs:51: // Add user arguments (skip "check" if it was the first arg) +/Users/andrew/Programming/rtk/src/ruff_cmd.rs:70: // Format or other commands - pass through +/Users/andrew/Programming/rtk/src/ruff_cmd.rs:93: // Fallback for other commands (version, etc.) +/Users/andrew/Programming/rtk/src/ruff_cmd.rs:292: result.push_str("\n💡 Run `ruff format` to format these files\n"); +/Users/andrew/Programming/rtk/src/ruff_cmd.rs:295: // Write mode or other output - show summary +/Users/andrew/Programming/rtk/src/grep_cmd.rs:207: // Test that the function signature accepts extra_args +/Users/andrew/Programming/rtk/src/grep_cmd.rs:208: // This is a compile-time test - if it compiles, the signature is correct +/Users/andrew/Programming/rtk/src/grep_cmd.rs:210: // No need to actually run - we're verifying the parameter exists +/Users/andrew/Programming/rtk/src/json_cmd.rs:51:/// Useful for piping JSON from other commands (e.g., `gh api`, `curl`). +/Users/andrew/Programming/rtk/src/read.rs:27: .and_then(|e| e.to_str()) +/Users/andrew/Programming/rtk/src/read.rs:171: // Compile-time verification that the function exists with correct signature +/Users/andrew/Programming/rtk/src/vitest_cmd.rs:152: let duration_ms = DURATION_RE.captures(&clean_output).and_then(|caps| { +/Users/andrew/Programming/rtk/src/tracking.rs:203: /// Opens or creates the SQLite database at the platform-specific location. +/Users/andrew/Programming/rtk/src/tracking.rs:204: /// Automatically creates the `commands` table if it doesn't exist and runs +/Users/andrew/Programming/rtk/src/tracking.rs:260: /// Calculates savings metrics and stores the record in the database. +/Users/andrew/Programming/rtk/src/tracking.rs:726:/// and records token savings. Use instead of the deprecated [`track`] function. +/Users/andrew/Programming/rtk/src/tracking.rs:748: /// when the command completes. +/Users/andrew/Programming/rtk/src/tracking.rs:765: /// Track the command with elapsed time and token counts. +/Users/andrew/Programming/rtk/src/tracking.rs:767: /// Records the command execution with: +/Users/andrew/Programming/rtk/src/tracking.rs:920: // Use unique test identifier to avoid conflicts with other tests +/Users/andrew/Programming/rtk/src/tracking.rs:980: // because the savings calculation is correct for both cases +/Users/andrew/Programming/rtk/src/main.rs:58: long_about = "A high-performance CLI proxy designed to filter and summarize system outputs before they reach your LLM context." +/Users/andrew/Programming/rtk/src/main.rs:620: Other(Vec), +/Users/andrew/Programming/rtk/src/main.rs:662: Other(Vec), +/Users/andrew/Programming/rtk/src/main.rs:675: Other(Vec), +/Users/andrew/Programming/rtk/src/main.rs:704: Other(Vec), +/Users/andrew/Programming/rtk/src/main.rs:797: Other(Vec), +/Users/andrew/Programming/rtk/src/main.rs:822: Other(Vec), +/Users/andrew/Programming/rtk/src/main.rs:900: GitCommands::Other(args) => { +/Users/andrew/Programming/rtk/src/main.rs:929: PnpmCommands::Other(args) => { +/Users/andrew/Programming/rtk/src/main.rs:995: DockerCommands::Other(args) => { +/Users/andrew/Programming/rtk/src/main.rs:1029: KubectlCommands::Other(args) => { +/Users/andrew/Programming/rtk/src/main.rs:1243: CargoCommands::Other(args) => { +/Users/andrew/Programming/rtk/src/main.rs:1319: // Passthrough other prisma subcommands +/Users/andrew/Programming/rtk/src/main.rs:1386: GoCommands::Other(args) => { +/Users/andrew/Programming/rtk/src/main.rs:1387: go_cmd::run_other(&args, cli.verbose)?; +/Users/andrew/Programming/rtk/src/init.rs:339: let hooks = match root.get_mut("hooks").and_then(|h| h.get_mut("PreToolUse")) { +/Users/andrew/Programming/rtk/src/init.rs:352: if let Some(hooks_array) = entry.get("hooks").and_then(|h| h.as_array()) { +/Users/andrew/Programming/rtk/src/init.rs:354: if let Some(command) = hook.get("command").and_then(|c| c.as_str()) { +/Users/andrew/Programming/rtk/src/init.rs:631: .and_then(|h| h.get("PreToolUse")) +/Users/andrew/Programming/rtk/src/init.rs:632: .and_then(|p| p.as_array()) +/Users/andrew/Programming/rtk/src/init.rs:713:/// Hook-only mode: just the hook, no RTK.md +/Users/andrew/Programming/rtk/src/init.rs:808: eprintln!(" Action: Manually remove the incomplete block, then re-run:"); +/Users/andrew/Programming/rtk/src/init.rs:960: eprintln!(" Action: Manually remove the incomplete block, then re-run:"); +/Users/andrew/Programming/rtk/src/init.rs:1190: // Just verify RTK_INSTRUCTIONS constant has the right content +/Users/andrew/Programming/rtk/src/init.rs:1339: fn test_hook_not_present_other_hooks() { +/Users/andrew/Programming/rtk/src/init.rs:1346: "command": "/some/other/hook.sh" +/Users/andrew/Programming/rtk/src/init.rs:1387: "command": "/some/other/hook.sh" +/Users/andrew/Programming/rtk/src/init.rs:1401: assert_eq!(first_command, "/some/other/hook.sh"); +/Users/andrew/Programming/rtk/src/init.rs:1409: fn test_insert_hook_preserves_other_keys() { +/Users/andrew/Programming/rtk/src/init.rs:1419: // Should preserve all other keys +/Users/andrew/Programming/rtk/src/init.rs:1489: "command": "/some/other/hook.sh" +/Users/andrew/Programming/rtk/src/init.rs:1510: // Check it's the other hook +/Users/andrew/Programming/rtk/src/init.rs:1512: assert_eq!(command, "/some/other/hook.sh"); +/Users/andrew/Programming/rtk/src/init.rs:1523: "command": "/some/other/hook.sh" +/Users/andrew/Programming/rtk/src/filter.rs:180: // Handle Python docstrings (keep them in minimal mode) +/Users/andrew/Programming/rtk/src/filter.rs:273: // Only keep the opening and closing braces +/Users/andrew/Programming/rtk/src/prettier_cmd.rs:163:Code style issues found in the above file(s). Forgot to run Prettier? +/Users/andrew/Programming/rtk/src/env_cmd.rs:23: let mut other_vars = Vec::new(); +/Users/andrew/Programming/rtk/src/env_cmd.rs:59: other_vars.push(entry); +/Users/andrew/Programming/rtk/src/env_cmd.rs:104: if !other_vars.is_empty() { +/Users/andrew/Programming/rtk/src/env_cmd.rs:105: println!("\n📋 Other:"); +/Users/andrew/Programming/rtk/src/env_cmd.rs:106: for (k, v) in other_vars.iter().take(20) { +/Users/andrew/Programming/rtk/src/env_cmd.rs:109: if other_vars.len() > 20 { +/Users/andrew/Programming/rtk/src/env_cmd.rs:110: println!(" ... +{} more", other_vars.len() - 20); +/Users/andrew/Programming/rtk/src/env_cmd.rs:119: + other_vars.len().min(20); +/Users/andrew/Programming/rtk/src/container.rs:331: .or_else(|| p["targetPort"].as_str().and_then(|s| s.parse().ok())) +/Users/andrew/Programming/rtk/src/container.rs:393: // Extract just the port numbers +/Users/andrew/Programming/rtk/src/container.rs:396: .filter_map(|p| p.split("->").next().and_then(|s| s.split(':').last())) +/Users/andrew/Programming/rtk/src/utils.rs:175:/// Detect the package manager used in the current directory. +/Users/andrew/Programming/rtk/src/utils.rs:195:/// Build a Command using the detected package manager's exec mechanism. +/Users/andrew/Programming/rtk/src/utils.rs:369: // In the test environment (rtk repo), there's no JS lockfile +/Users/andrew/Programming/rtk/src/gh_cmd.rs:863: // gh pr create outputs the URL on success +/Users/andrew/Programming/rtk/src/playwright_cmd.rs:121: .and_then(|r| r.error.as_ref()) +/Users/andrew/Programming/rtk/src/playwright_cmd.rs:168: let duration_ms = DURATION_RE.captures(&clean_output).and_then(|caps| { +/Users/andrew/Programming/rtk/src/summary.rs:101: .then_some(true) +/Users/andrew/Programming/rtk/src/summary.rs:295: .and_then(|c| c.get(1)) +/Users/andrew/Programming/rtk/src/summary.rs:296: .and_then(|m| m.as_str().parse().ok()) diff --git a/benchmarks/quality_samples/E1_head_n.txt b/benchmarks/quality_samples/E1_head_n.txt new file mode 100644 index 0000000..34ac4fd --- /dev/null +++ b/benchmarks/quality_samples/E1_head_n.txt @@ -0,0 +1,100 @@ +/Users/andrew/Programming/rtk/src/pip_cmd.rs:163: .and_then(|o| String::from_utf8(o.stdout).ok()) +/Users/andrew/Programming/rtk/src/pytest_cmd.rs:85: .and_then(|o| String::from_utf8(o.stdout).ok()) +/Users/andrew/Programming/rtk/src/ls.rs:52: // Build ls -la + any extra flags the user passed (e.g. -R) +/Users/andrew/Programming/rtk/src/ls.rs:53: // Strip -l, -a, -h (we handle all of these ourselves) +/Users/andrew/Programming/rtk/src/local_llm.rs:19: .and_then(|e| e.to_str()) +/Users/andrew/Programming/rtk/src/local_llm.rs:62: (!functions.is_empty()).then(|| format!("{} fn", functions.len())), +/Users/andrew/Programming/rtk/src/local_llm.rs:63: (!structs.is_empty()).then(|| format!("{} struct", structs.len())), +/Users/andrew/Programming/rtk/src/local_llm.rs:64: (!traits.is_empty()).then(|| format!("{} trait", traits.len())), +/Users/andrew/Programming/rtk/src/learn/detector.rs:12: Other(String), +/Users/andrew/Programming/rtk/src/learn/detector.rs:24: ErrorType::Other(s) => s, +/Users/andrew/Programming/rtk/src/learn/detector.rs:58: r"(?i)(no such file or directory|cannot find the path|file not found)" +/Users/andrew/Programming/rtk/src/learn/detector.rs:109: ErrorType::Other("General Error".to_string()) +/Users/andrew/Programming/rtk/src/learn/detector.rs:194: matches!(error_type, ErrorType::CommandNotFound | ErrorType::Other(_)) +/Users/andrew/Programming/rtk/src/learn/detector.rs:282:/// Extract the specific token that changed between wrong and right commands +/Users/andrew/Programming/rtk/src/learn/detector.rs:293: // Return the most distinctive change +/Users/andrew/Programming/rtk/src/learn/detector.rs:320: // For each group, keep the best confidence example +/Users/andrew/Programming/rtk/src/learn/detector.rs:421: ErrorType::Other(_) +/Users/andrew/Programming/rtk/src/learn/detector.rs:544: // Let me adjust: they have same base "cat" but different args +/Users/andrew/Programming/rtk/src/learn/mod.rs:37: println!("No Claude Code sessions found in the last {} days.", since); +/Users/andrew/Programming/rtk/src/discover/registry.rs:287: "then\n", +/Users/andrew/Programming/rtk/src/discover/registry.rs:288: "then ", +/Users/andrew/Programming/rtk/src/discover/registry.rs:339: // Fast check with RegexSet — take the last (most specific) match +/Users/andrew/Programming/rtk/src/discover/registry.rs:391:/// Extract the base command (first word, or first two if it looks like a subcommand pattern). +/Users/andrew/Programming/rtk/src/discover/registry.rs:399: // If the second token looks like a subcommand (no leading -) +/Users/andrew/Programming/rtk/src/discover/registry.rs:404: .and_then(|i| { +/Users/andrew/Programming/rtk/src/discover/registry.rs:421:/// For pipes `|`, only keep the first command. +/Users/andrew/Programming/rtk/src/discover/registry.rs:625: other => panic!("expected Unsupported, got {:?}", other), +/Users/andrew/Programming/rtk/src/discover/registry.rs:719: // except Other has a matching pattern in the registry +/Users/andrew/Programming/rtk/src/discover/registry.rs:724: other => panic!("cargo {subcmd} should be Supported, got {other:?}"), +/Users/andrew/Programming/rtk/src/discover/registry.rs:739: other => panic!("git {subcmd} should be Supported, got {other:?}"), +/Users/andrew/Programming/rtk/src/discover/provider.rs:18: /// Whether the tool_result indicated an error +/Users/andrew/Programming/rtk/src/discover/provider.rs:20: /// Chronological sequence index within the session +/Users/andrew/Programming/rtk/src/discover/provider.rs:37: /// Get the base directory for Claude Code projects. +/Users/andrew/Programming/rtk/src/discover/provider.rs:84: let dir_name = path.file_name().and_then(|n| n.to_str()).unwrap_or(""); +/Users/andrew/Programming/rtk/src/discover/provider.rs:90: // Walk the project directory recursively (catches subagents/) +/Users/andrew/Programming/rtk/src/discover/provider.rs:97: if file_path.extension().and_then(|e| e.to_str()) != Some("jsonl") { +/Users/andrew/Programming/rtk/src/discover/provider.rs:126: .and_then(|s| s.to_str()) +/Users/andrew/Programming/rtk/src/discover/provider.rs:130: // First pass: collect all tool_use Bash commands with their IDs and sequence +/Users/andrew/Programming/rtk/src/discover/provider.rs:153: let entry_type = entry.get("type").and_then(|t| t.as_str()).unwrap_or(""); +/Users/andrew/Programming/rtk/src/discover/provider.rs:159: entry.pointer("/message/content").and_then(|c| c.as_array()) +/Users/andrew/Programming/rtk/src/discover/provider.rs:162: if block.get("type").and_then(|t| t.as_str()) == Some("tool_use") +/Users/andrew/Programming/rtk/src/discover/provider.rs:163: && block.get("name").and_then(|n| n.as_str()) == Some("Bash") +/Users/andrew/Programming/rtk/src/discover/provider.rs:166: block.get("id").and_then(|i| i.as_str()), +/Users/andrew/Programming/rtk/src/discover/provider.rs:167: block.pointer("/input/command").and_then(|c| c.as_str()), +/Users/andrew/Programming/rtk/src/discover/provider.rs:183: entry.pointer("/message/content").and_then(|c| c.as_array()) +/Users/andrew/Programming/rtk/src/discover/provider.rs:186: if block.get("type").and_then(|t| t.as_str()) == Some("tool_result") { +/Users/andrew/Programming/rtk/src/discover/provider.rs:187: if let Some(id) = block.get("tool_use_id").and_then(|i| i.as_str()) +/Users/andrew/Programming/rtk/src/discover/provider.rs:191: block.get("content").and_then(|c| c.as_str()).unwrap_or(""); +/Users/andrew/Programming/rtk/src/discover/provider.rs:196: .and_then(|e| e.as_bool()) +/Users/andrew/Programming/rtk/src/discover/provider.rs:216: // Match tool_uses with their results +/Users/andrew/Programming/rtk/src/discover/report.rs:8: /// Works via external_subcommand passthrough, no filtering (e.g., cargo fmt → Other) +/Users/andrew/Programming/rtk/src/discover/report.rs:177: // UTF-8 safe truncation: collect chars up to max-2, then add ".." +/Users/andrew/Programming/rtk/src/discover/mod.rs:19: // For display: the most common raw command +/Users/andrew/Programming/rtk/src/discover/mod.rs:118: // Track the display name with status +/Users/andrew/Programming/rtk/src/discover/mod.rs:140: // Otherwise just skip +/Users/andrew/Programming/rtk/src/discover/mod.rs:151: // Pick the most common command as the display name +/Users/andrew/Programming/rtk/src/discover/mod.rs:218:/// Extract the subcommand from a command string (second word). +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:419: /// Merge another test result into this one +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:420: fn merge(&mut self, other: &Self) { +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:421: self.passed += other.passed; +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:422: self.failed += other.failed; +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:423: self.ignored += other.ignored; +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:424: self.measured += other.measured; +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:425: self.filtered_out += other.filtered_out; +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:426: self.suites += other.suites; +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:427: self.duration_secs += other.duration_secs; +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:428: self.has_duration = self.has_duration && other.has_duration; +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:628: // No bracket: use the message itself as the rule +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:836: // Should NOT aggregate when there are failures +/Users/andrew/Programming/rtk/src/ccusage.rs:94:/// Build the ccusage command, falling back to npx if binary not in PATH +/Users/andrew/Programming/rtk/src/ccusage.rs:122:/// Fetch usage data from ccusage for the last 90 days +/Users/andrew/Programming/rtk/src/go_cmd.rs:171:pub fn run_other(args: &[OsString], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/lint_cmd.rs:31: // Detect if eslint or other linter (ignore paths containing / or .) +/Users/andrew/Programming/rtk/src/lint_cmd.rs:46: // Add user arguments (skip first if it was the linter name) +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:27:/// Create a Command that will run prisma (tries global first, then npx) +/Users/andrew/Programming/rtk/src/cc_economics.rs:506: println!(" RTK compresses CLI outputs before they enter Claude's context."); +/Users/andrew/Programming/rtk/src/find_cmd.rs:249: // run() converts "." to "*" internally, test the logic +/Users/andrew/Programming/rtk/src/git.rs:79: // Default RTK behavior: stat first, then compacted diff +/Users/andrew/Programming/rtk/src/git.rs:314: // Apply RTK defaults only if user didn't specify them +/Users/andrew/Programming/rtk/src/git.rs:328: .and_then(|arg| arg[1..].parse::().ok()) +/Users/andrew/Programming/rtk/src/git.rs:817: .and_then(|n| n.parse().ok()) +/Users/andrew/Programming/rtk/src/git.rs:823: .and_then(|n| n.parse().ok()) +/Users/andrew/Programming/rtk/src/git.rs:829: .and_then(|n| n.parse().ok()) +/Users/andrew/Programming/rtk/src/git.rs:1422: // Compile-time verification that the function exists with correct signature +/Users/andrew/Programming/rtk/src/git.rs:1427: let output = "abc1234 This is a commit message (2 days ago) \ndef5678 Another commit (1 week ago) \n"; +/Users/andrew/Programming/rtk/src/git.rs:1489: // The line has 30 Thai chars (90 bytes) + other text, so > 80 bytes +/Users/andrew/Programming/rtk/src/deps.rs:132: if let Some(name) = json.get("name").and_then(|v| v.as_str()) { +/Users/andrew/Programming/rtk/src/deps.rs:133: let version = json.get("version").and_then(|v| v.as_str()).unwrap_or("?"); +/Users/andrew/Programming/rtk/src/deps.rs:136: if let Some(deps) = json.get("dependencies").and_then(|v| v.as_object()) { +/Users/andrew/Programming/rtk/src/deps.rs:150: if let Some(dev_deps) = json.get("devDependencies").and_then(|v| v.as_object()) { +/Users/andrew/Programming/rtk/src/parser/error.rs:35: Other(#[from] anyhow::Error), +/Users/andrew/Programming/rtk/src/parser/mod.rs:31: /// Unwrap the parsed data, panicking on Passthrough +/Users/andrew/Programming/rtk/src/parser/mod.rs:40: /// Get the tier level (1 = Full, 2 = Degraded, 3 = Passthrough) +/Users/andrew/Programming/rtk/src/parser/mod.rs:54: /// Map the parsed data while preserving tier +/Users/andrew/Programming/rtk/src/parser/mod.rs:179: let end_pos = start_pos + i + 1; // +1 to include the `}` +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:571: // Compile-time verification that the function exists with correct signature +/Users/andrew/Programming/rtk/src/tree.rs:3://! This module proxies to the native `tree` command and filters the output +/Users/andrew/Programming/rtk/src/tree.rs:115: // Skip the final summary line (e.g., "5 directories, 23 files") +/Users/andrew/Programming/rtk/src/tree.rs:120: // Skip empty lines at the end +/Users/andrew/Programming/rtk/src/log_cmd.rs:48:/// For use by other modules diff --git a/benchmarks/quality_samples/E1_rtk_grep.txt b/benchmarks/quality_samples/E1_rtk_grep.txt new file mode 100644 index 0000000..21a4fc9 --- /dev/null +++ b/benchmarks/quality_samples/E1_rtk_grep.txt @@ -0,0 +1,239 @@ +🔍 178 in 40F: + +📄 /Users/andrew/Programming/rtk/src/cargo_cmd.rs (12): + 419: /// Merge another test result into this one + 420: fn merge(&mut self, other: &Self) { + 421: self.passed += other.passed; + 422: self.failed += other.failed; + 423: self.ignored += other.ignored; + 424: self.measured += other.measured; + 425: self.filtered_out += other.filtered_out; + 426: self.suites += other.suites; + 427: self.duration_secs += other.duration_secs; + 428: self.has_duration = self.has_duration && other.has_duration; + +2 + +📄 /Users/andrew/Programming/rtk/src/cc_economics.rs (1): + 506: println!(" RTK compresses CLI outputs before they enter Claude's context."); + +📄 /Users/andrew/Programming/rtk/src/ccusage.rs (2): + 94: /// Build the ccusage command, falling back to npx if binary not in PATH + 122: /// Fetch usage data from ccusage for the last 90 days + +📄 /Users/andrew/Programming/rtk/src/container.rs (3): + 331: .or_else(|| p["targetPort"].as_str().and_then(|s| s.parse().ok())) + 393: // Extract just the port numbers + 396: .filter_map(|p| p.split("->").next().and_then(|s| s.split(':').last())) + +📄 /Users/andrew/Programming/rtk/src/deps.rs (4): + 132: if let Some(name) = json.get("name").and_then(|v| v.as_str()) { + 133: let version = json.get("version").and_then(|v| v.as_str()).unwrap_or("?"); + 136: if let Some(deps) = json.get("dependencies").and_then(|v| v.as_object()) { + 150: ...f let Some(dev_deps) = json.get("devDependencies").and_then(|v| v.as_object()) { + +📄 /Users/andrew/Programming/rtk/src/discover/mod.rs (5): + 19: // For display: the most common raw command + 118: // Track the display name with status + 140: // Otherwise just skip + 151: // Pick the most common command as the display name + 218: /// Extract the subcommand from a command string (second word). + +📄 /.../discover/provider.rs (20): + 18: /// Whether the tool_result indicated an error + 20: /// Chronological sequence index within the session + 37: /// Get the base directory for Claude Code projects. + 84: let dir_name = path.file_name().and_then(|n| n.to_str()).unwrap_or(""); + 90: // Walk the project directory recursively (catches subagents/) + 97: if file_path.extension().and_then(|e| e.to_str()) != Some("jsonl") { + 126: .and_then(|s| s.to_str()) + 130: // First pass: collect all tool_use Bash commands with their IDs and sequence + 153: let entry_type = entry.get("type").and_then(|t| t.as_str()).unwrap_or(""); + 159: entry.pointer("/message/content").and_then(|c| c.as_array()) + +10 + +📄 /.../discover/registry.rs (11): + 287: "then\n", + 288: "then ", + 339: // Fast check with RegexSet — take the last (most specific) match + 391: /// Extract the base command (first word, or first two if it looks like a subcom... + 399: // If the second token looks like a subcommand (no leading -) + 404: .and_then(|i| { + 421: /// For pipes `|`, only keep the first command. + 625: other => panic!("expected Unsupported, got {:?}", other), + 719: // except Other has a matching pattern in the registry + 724: other => panic!("cargo {subcmd} should be Supported, got {other:?}"), + +1 + +📄 /.../discover/report.rs (2): + 8: ...orks via external_subcommand passthrough, no filtering (e.g., cargo fmt → Other) + 177: // UTF-8 safe truncation: collect chars up to max-2, then add ".." + +📄 /Users/andrew/Programming/rtk/src/env_cmd.rs (8): + 23: let mut other_vars = Vec::new(); + 59: other_vars.push(entry); + 104: if !other_vars.is_empty() { + 105: println!("\n📋 Other:"); + 106: for (k, v) in other_vars.iter().take(20) { + 109: if other_vars.len() > 20 { + 110: println!(" ... +{} more", other_vars.len() - 20); + 119: + other_vars.len().min(20); + +📄 /Users/andrew/Programming/rtk/src/filter.rs (2): + 180: // Handle Python docstrings (keep them in minimal mode) + 273: // Only keep the opening and closing braces + +📄 /Users/andrew/Programming/rtk/src/find_cmd.rs (1): + 249: // run() converts "." to "*" internally, test the logic + +📄 /Users/andrew/Programming/rtk/src/gh_cmd.rs (1): + 863: // gh pr create outputs the URL on success + +📄 /Users/andrew/Programming/rtk/src/git.rs (9): + 79: // Default RTK behavior: stat first, then compacted diff + 314: // Apply RTK defaults only if user didn't specify them + 328: .and_then(|arg| arg[1..].parse::().ok()) + 817: .and_then(|n| n.parse().ok()) + 823: .and_then(|n| n.parse().ok()) + 829: .and_then(|n| n.parse().ok()) + 1422: // Compile-time verification that the function exists with correct signature + 1427: ...t message (2 days ago) \ndef5678 Another commit (1 week ago) \n"; + 1489: // The line has 30 Thai chars (90 bytes) + other text, so > 80 bytes + +📄 /Users/andrew/Programming/rtk/src/go_cmd.rs (1): + 171: pub fn run_other(args: &[OsString], verbose: u8) -> Result<()> { + +📄 /Users/andrew/Programming/rtk/src/grep_cmd.rs (3): + 207: // Test that the function signature accepts extra_args + 208: // This is a compile-time test - if it compiles, the signature is correct + 210: // No need to actually run - we're verifying the parameter exists + +📄 /Users/andrew/Programming/rtk/src/init.rs (19): + 339: let hooks = match root.get_mut("hooks").and_then(|h| h.get_mut("PreToolUse")) { + 352: if let Some(hooks_array) = entry.get("hooks").and_then(|h| h.as_array()) { + 354: if let Some(command) = hook.get("command").and_then(|c| c.as_str()) { + 631: .and_then(|h| h.get("PreToolUse")) + 632: .and_then(|p| p.as_array()) + 713: /// Hook-only mode: just the hook, no RTK.md + 808: eprintln!(" Action: Manually remove the incomplete block, then re-run:"); + 960: eprintln!(" Action: Manually remove the incomplete block, then re-run:"); + 1190: // Just verify RTK_INSTRUCTIONS constant has the right content + 1339: fn test_hook_not_present_other_hooks() { + +9 + +📄 /Users/andrew/Programming/rtk/src/json_cmd.rs (1): + 51: /// Useful for piping JSON from other commands (e.g., `gh api`, `curl`). + +📄 /.../learn/detector.rs (10): + 12: Other(String), + 24: ErrorType::Other(s) => s, + 58: r"(?i)(no such file or directory|cannot find the path|file not found)" + 109: ErrorType::Other("General Error".to_string()) + 194: matches!(error_type, ErrorType::CommandNotFound | ErrorType::Other(_)) + 282: /// Extract the specific token that changed between wrong and right commands + 293: // Return the most distinctive change + 320: // For each group, keep the best confidence example + 421: ErrorType::Other(_) + 544: // Let me adjust: they have same base "cat" but different args + +📄 /Users/andrew/Programming/rtk/src/learn/mod.rs (1): + 37: println!("No Claude Code sessions found in the last {} days.", since); + +📄 /Users/andrew/Programming/rtk/src/lint_cmd.rs (2): + 31: // Detect if eslint or other linter (ignore paths containing / or .) + 46: // Add user arguments (skip first if it was the linter name) + +📄 /Users/andrew/Programming/rtk/src/local_llm.rs (4): + 19: .and_then(|e| e.to_str()) + 62: (!functions.is_empty()).then(|| format!("{} fn", functions.len())), + 63: (!structs.is_empty()).then(|| format!("{} struct", structs.len())), + 64: (!traits.is_empty()).then(|| format!("{} trait", traits.len())), + +📄 /Users/andrew/Programming/rtk/src/log_cmd.rs (1): + 48: /// For use by other modules + +📄 /Users/andrew/Programming/rtk/src/ls.rs (2): + 52: // Build ls -la + any extra flags the user passed (e.g. -R) + 53: // Strip -l, -a, -h (we handle all of these ourselves) + +📄 /Users/andrew/Programming/rtk/src/main.rs (15): + 58: ...gned to filter and summarize system outputs before they reach your LLM context." + 620: Other(Vec), + 662: Other(Vec), + 675: Other(Vec), + 704: Other(Vec), + 797: Other(Vec), + 822: Other(Vec), + 900: GitCommands::Other(args) => { + 929: PnpmCommands::Other(args) => { + 995: DockerCommands::Other(args) => { + +5 + +📄 /Users/andrew/Programming/rtk/src/parser/error.rs (1): + 35: Other(#[from] anyhow::Error), + +📄 /Users/andrew/Programming/rtk/src/parser/mod.rs (4): + 31: /// Unwrap the parsed data, panicking on Passthrough + 40: /// Get the tier level (1 = Full, 2 = Degraded, 3 = Passthrough) + 54: /// Map the parsed data while preserving tier + 179: let end_pos = start_pos + i + 1; // +1 to include the `}` + +📄 /Users/andrew/Programming/rtk/src/pip_cmd.rs (1): + 163: .and_then(|o| String::from_utf8(o.stdout).ok()) + +📄 /.../src/playwright_cmd.rs (2): + 121: .and_then(|r| r.error.as_ref()) + 168: let duration_ms = DURATION_RE.captures(&clean_output).and_then(|caps| { + +📄 /Users/andrew/Programming/rtk/src/pnpm_cmd.rs (1): + 571: // Compile-time verification that the function exists with correct signature + +📄 /Users/andrew/Programming/rtk/src/prettier_cmd.rs (1): + 163: Code style issues found in the above file(s). Forgot to run Prettier? + +📄 /Users/andrew/Programming/rtk/src/prisma_cmd.rs (1): + 27: /// Create a Command that will run prisma (tries global first, then npx) + +📄 /Users/andrew/Programming/rtk/src/pytest_cmd.rs (1): + 85: .and_then(|o| String::from_utf8(o.stdout).ok()) + +📄 /Users/andrew/Programming/rtk/src/read.rs (2): + 27: .and_then(|e| e.to_str()) + 171: // Compile-time verification that the function exists with correct signature + +📄 /Users/andrew/Programming/rtk/src/ruff_cmd.rs (5): + 51: // Add user arguments (skip "check" if it was the first arg) + 70: // Format or other commands - pass through + 93: // Fallback for other commands (version, etc.) + 292: result.push_str("\n💡 Run `ruff format` to format these files\n"); + 295: // Write mode or other output - show summary + +📄 /Users/andrew/Programming/rtk/src/summary.rs (3): + 101: .then_some(true) + 295: .and_then(|c| c.get(1)) + 296: .and_then(|m| m.as_str().parse().ok()) + +📄 /Users/andrew/Programming/rtk/src/tracking.rs (9): + 203: /// Opens or creates the SQLite database at the platform-specific location. + 204: /// Automatically creates the `commands` table if it doesn't exist and runs + 260: /// Calculates savings metrics and stores the record in the database. + 726: /// and records token savings. Use instead of the deprecated [`track`] function. + 748: /// when the command completes. + 765: /// Track the command with elapsed time and token counts. + 767: /// Records the command execution with: + 920: // Use unique test identifier to avoid conflicts with other tests + 980: // because the savings calculation is correct for both cases + +📄 /Users/andrew/Programming/rtk/src/tree.rs (3): + 3: //! This module proxies to the native `tree` command and filters the output + 115: // Skip the final summary line (e.g., "5 directories, 23 files") + 120: // Skip empty lines at the end + +📄 /Users/andrew/Programming/rtk/src/utils.rs (3): + 175: /// Detect the package manager used in the current directory. + 195: /// Build a Command using the detected package manager's exec mechanism. + 369: // In the test environment (rtk repo), there's no JS lockfile + +📄 /Users/andrew/Programming/rtk/src/vitest_cmd.rs (1): + 152: let duration_ms = DURATION_RE.captures(&clean_output).and_then(|caps| { + +... +27 diff --git a/benchmarks/quality_samples/E1_rtk_rgai.txt b/benchmarks/quality_samples/E1_rtk_rgai.txt new file mode 100644 index 0000000..45c6c96 --- /dev/null +++ b/benchmarks/quality_samples/E1_rtk_rgai.txt @@ -0,0 +1,106 @@ +🧠 42F for 'the' (scan 55F) + +📄 init.rs [17.4] + 1338: #[test] + 1339: fn test_hook_not_present_other_hooks() { + 1340: let json_content = serde_json::json!({ + ~ the + + 1408: #[test] + 1409: fn test_insert_hook_preserves_other_keys() { + 1410: let mut json_content = serde_json::json!({ + ~ the + + +18 more lines + +📄 cargo_cmd.rs [15.8] + 419: /// Merge another test result into this one + 420: fn merge(&mut self, other: &Self) { + 421: self.passed += other.passed; + ~ the + + 423: self.ignored += other.ignored; + 424: self.measured += other.measured; + 425: self.filtered_out += other.filtered_out; + ~ the + + +10 more lines + +📄 discover/provider.rs [13.8] + 83: if let Some(filter) = project_filter { + 84: let dir_name = path.file_name().and_then(|n| n.to_str()).unwrap_or(""); + 85: if !dir_name.contains(filter) { + ~ the + + 96: let file_path = walk_entry.path(); + 97: if file_path.extension().and_then(|e| e.to_str()) != Some("jsonl") { + 98: continue; + ~ the + + +18 more lines + +📄 main.rs [13.5] + 57: about = "Rust Token Killer - Minimize LLM token consumption", + 58: long_about = "A high-performance CLI proxy designed to filter and summarize system outputs before they reach your LLM context." + 59: )] + ~ the + + 619: #[command(external_subcommand)] + 620: Other(Vec), + 621: } + ~ the + + +13 more lines + +📄 discover/registry.rs [13.2] + 286: "sh ", + 287: "then\n", + 288: "then ", + ~ the + + 403: .find(char::is_whitespace) + 404: .and_then(|i| { + 405: let rest = &cmd[i..]; + ~ the + + +9 more lines + +📄 learn/detector.rs [13.2] + 11: PermissionDenied, + 12: Other(String), + 13: } + ~ the + + 23: ErrorType::PermissionDenied => "Permission Denied", + 24: ErrorType::Other(s) => s, + 25: } + ~ the + + +9 more lines + +📄 git.rs [13.0] + 327: }) + 328: .and_then(|arg| arg[1..].parse::().ok()) + 329: .unwrap_or(10) + ~ the + + 816: .next() + 817: .and_then(|n| n.parse().ok()) + 818: .unwrap_or(0); + ~ the + + +7 more lines + +📄 env_cmd.rs [12.9] + 22: let mut tool_vars = Vec::new(); + 23: let mut other_vars = Vec::new(); + ~ the + + 58: } else if filter.is_some() || is_interesting_var(key) { + 59: other_vars.push(entry); + 60: } + ~ the + + +6 more lines + +... +34F diff --git a/benchmarks/quality_samples/E2_grep.txt b/benchmarks/quality_samples/E2_grep.txt new file mode 100644 index 0000000..749906b --- /dev/null +++ b/benchmarks/quality_samples/E2_grep.txt @@ -0,0 +1,784 @@ +/Users/andrew/Programming/rtk/src/pip_cmd.rs:14:pub fn run(args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/pip_cmd.rs:53:fn run_list(base_cmd: &str, args: &[String], verbose: u8) -> Result<(String, String)> { +/Users/andrew/Programming/rtk/src/pip_cmd.rs:88:fn run_outdated(base_cmd: &str, args: &[String], verbose: u8) -> Result<(String, String)> { +/Users/andrew/Programming/rtk/src/pip_cmd.rs:123:fn run_passthrough(base_cmd: &str, args: &[String], verbose: u8) -> Result<(String, String)> { +/Users/andrew/Programming/rtk/src/pip_cmd.rs:157:fn which_command(cmd: &str) -> Option { +/Users/andrew/Programming/rtk/src/pip_cmd.rs:169:fn filter_pip_list(output: &str) -> String { +/Users/andrew/Programming/rtk/src/pip_cmd.rs:214:fn filter_pip_outdated(output: &str) -> String { +/Users/andrew/Programming/rtk/src/pip_cmd.rs:259: fn test_filter_pip_list() { +/Users/andrew/Programming/rtk/src/pip_cmd.rs:274: fn test_filter_pip_list_empty() { +/Users/andrew/Programming/rtk/src/pip_cmd.rs:281: fn test_filter_pip_outdated_none() { +/Users/andrew/Programming/rtk/src/pip_cmd.rs:289: fn test_filter_pip_outdated_some() { +/Users/andrew/Programming/rtk/src/pytest_cmd.rs:14:pub fn run(args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/pytest_cmd.rs:79:fn which_command(cmd: &str) -> Option { +/Users/andrew/Programming/rtk/src/pytest_cmd.rs:91:fn filter_pytest_output(output: &str) -> String { +/Users/andrew/Programming/rtk/src/pytest_cmd.rs:170:fn build_pytest_summary(summary: &str, _test_files: &[String], failures: &[String]) -> String { +/Users/andrew/Programming/rtk/src/pytest_cmd.rs:249:fn parse_summary_line(summary: &str) -> (usize, usize, usize) { +/Users/andrew/Programming/rtk/src/pytest_cmd.rs:286: fn test_filter_pytest_all_pass() { +/Users/andrew/Programming/rtk/src/pytest_cmd.rs:301: fn test_filter_pytest_with_failures() { +/Users/andrew/Programming/rtk/src/pytest_cmd.rs:327: fn test_filter_pytest_multiple_failures() { +/Users/andrew/Programming/rtk/src/pytest_cmd.rs:354: fn test_filter_pytest_no_tests() { +/Users/andrew/Programming/rtk/src/pytest_cmd.rs:365: fn test_parse_summary_line() { +/Users/andrew/Programming/rtk/src/ls.rs:33:pub fn run(args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/ls.rs:124:fn human_size(bytes: u64) -> String { +/Users/andrew/Programming/rtk/src/ls.rs:137:fn compact_ls(raw: &str, show_all: bool) -> String { +/Users/andrew/Programming/rtk/src/ls.rs:233: fn test_compact_basic() { +/Users/andrew/Programming/rtk/src/ls.rs:254: fn test_compact_filters_noise() { +/Users/andrew/Programming/rtk/src/ls.rs:270: fn test_compact_show_all() { +/Users/andrew/Programming/rtk/src/ls.rs:280: fn test_compact_empty() { +/Users/andrew/Programming/rtk/src/ls.rs:287: fn test_compact_summary() { +/Users/andrew/Programming/rtk/src/ls.rs:300: fn test_human_size() { +/Users/andrew/Programming/rtk/src/ls.rs:310: fn test_compact_handles_filenames_with_spaces() { +/Users/andrew/Programming/rtk/src/ls.rs:318: fn test_compact_symlinks() { +/Users/andrew/Programming/rtk/src/local_llm.rs:9:pub fn run(file: &Path, _model: &str, _force_download: bool, verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/local_llm.rs:36:fn analyze_code(content: &str, lang: &Language) -> CodeSummary { +/Users/andrew/Programming/rtk/src/local_llm.rs:62: (!functions.is_empty()).then(|| format!("{} fn", functions.len())), +/Users/andrew/Programming/rtk/src/local_llm.rs:97: let key_fns: Vec<&str> = functions.iter().take(3).map(|s| s.as_str()).collect(); +/Users/andrew/Programming/rtk/src/local_llm.rs:99: details.push(format!("defines: {}", key_fns.join(", "))); +/Users/andrew/Programming/rtk/src/local_llm.rs:112:fn lang_display_name(lang: &Language) -> &'static str { +/Users/andrew/Programming/rtk/src/local_llm.rs:128:fn extract_imports(content: &str, lang: &Language) -> Vec { +/Users/andrew/Programming/rtk/src/local_llm.rs:159:fn is_std_import(name: &str, lang: &Language) -> bool { +/Users/andrew/Programming/rtk/src/local_llm.rs:167:fn extract_functions(content: &str, lang: &Language) -> Vec { +/Users/andrew/Programming/rtk/src/local_llm.rs:169: Language::Rust => r"(?:pub\s+)?(?:async\s+)?fn\s+([a-zA-Z_][a-zA-Z0-9_]*)", +/Users/andrew/Programming/rtk/src/local_llm.rs:195:fn extract_structs(content: &str, lang: &Language) -> Vec { +/Users/andrew/Programming/rtk/src/local_llm.rs:212:fn extract_traits(content: &str, lang: &Language) -> Vec { +/Users/andrew/Programming/rtk/src/local_llm.rs:226:fn detect_patterns(content: &str, lang: &Language) -> Vec { +/Users/andrew/Programming/rtk/src/local_llm.rs:279: fn test_rust_analysis() { +/Users/andrew/Programming/rtk/src/local_llm.rs:288:pub fn load_config() -> Result { +/Users/andrew/Programming/rtk/src/local_llm.rs:292:fn helper() {} +/Users/andrew/Programming/rtk/src/local_llm.rs:296: assert!(summary.line1.contains("fn")); +/Users/andrew/Programming/rtk/src/local_llm.rs:300: fn test_python_analysis() { +/Users/andrew/Programming/rtk/src/learn/detector.rs:16: pub fn as_str(&self) -> &str { +/Users/andrew/Programming/rtk/src/learn/detector.rs:76:pub fn is_command_error(is_error: bool, output: &str) -> bool { +/Users/andrew/Programming/rtk/src/learn/detector.rs:97:pub fn classify_error(output: &str) -> ErrorType { +/Users/andrew/Programming/rtk/src/learn/detector.rs:124:pub fn extract_base_command(cmd: &str) -> String { +/Users/andrew/Programming/rtk/src/learn/detector.rs:145:pub fn command_similarity(a: &str, b: &str) -> f64 { +/Users/andrew/Programming/rtk/src/learn/detector.rs:182:fn is_tdd_cycle_error(error_type: &ErrorType, output: &str) -> bool { +/Users/andrew/Programming/rtk/src/learn/detector.rs:199:fn differs_only_by_path(a: &str, b: &str) -> bool { +/Users/andrew/Programming/rtk/src/learn/detector.rs:213:pub fn find_corrections(commands: &[CommandExecution]) -> Vec { +/Users/andrew/Programming/rtk/src/learn/detector.rs:283:fn extract_diff_token(wrong: &str, right: &str) -> String { +/Users/andrew/Programming/rtk/src/learn/detector.rs:305:pub fn deduplicate_corrections(pairs: Vec) -> Vec { +/Users/andrew/Programming/rtk/src/learn/detector.rs:357: fn test_is_command_error_requires_error_flag() { +/Users/andrew/Programming/rtk/src/learn/detector.rs:363: fn test_is_command_error_filters_user_rejection() { +/Users/andrew/Programming/rtk/src/learn/detector.rs:370: fn test_is_command_error_requires_error_content() { +/Users/andrew/Programming/rtk/src/learn/detector.rs:378: fn test_classify_error_unknown_flag() { +/Users/andrew/Programming/rtk/src/learn/detector.rs:394: fn test_classify_error_command_not_found() { +/Users/andrew/Programming/rtk/src/learn/detector.rs:406: fn test_classify_error_all_types() { +/Users/andrew/Programming/rtk/src/learn/detector.rs:426: fn test_extract_base_command() { +/Users/andrew/Programming/rtk/src/learn/detector.rs:440: fn test_command_similarity_same_base() { +/Users/andrew/Programming/rtk/src/learn/detector.rs:451: fn test_find_corrections_basic() { +/Users/andrew/Programming/rtk/src/learn/detector.rs:473: fn test_find_corrections_window_limit() { +/Users/andrew/Programming/rtk/src/learn/detector.rs:508: fn test_find_corrections_excludes_tdd_cycle() { +/Users/andrew/Programming/rtk/src/learn/detector.rs:527: fn test_find_corrections_path_exploration() { +/Users/andrew/Programming/rtk/src/learn/detector.rs:549: fn test_find_corrections_min_confidence() { +/Users/andrew/Programming/rtk/src/learn/detector.rs:571: fn test_deduplicate_corrections_merges_same() { +/Users/andrew/Programming/rtk/src/learn/detector.rs:605: fn test_deduplicate_corrections_keeps_distinct() { +/Users/andrew/Programming/rtk/src/learn/report.rs:7:pub fn format_console_report( +/Users/andrew/Programming/rtk/src/learn/report.rs:52:pub fn write_rules_file(rules: &[CorrectionRule], path: &str) -> Result<()> { +/Users/andrew/Programming/rtk/src/learn/report.rs:110:fn capitalize_first(s: &str) -> String { +/Users/andrew/Programming/rtk/src/learn/report.rs:124: fn test_format_console_report_empty() { +/Users/andrew/Programming/rtk/src/learn/report.rs:132: fn test_format_console_report_with_rules() { +/Users/andrew/Programming/rtk/src/learn/report.rs:162: fn test_write_rules_file_markdown() { +/Users/andrew/Programming/rtk/src/learn/mod.rs:9:pub fn run( +/Users/andrew/Programming/rtk/src/discover/registry.rs:29:pub fn category_avg_tokens(category: &str, subcmd: &str) -> usize { +/Users/andrew/Programming/rtk/src/discover/registry.rs:314:pub fn classify_command(cmd: &str) -> Classification { +/Users/andrew/Programming/rtk/src/discover/registry.rs:392:fn extract_base_command(cmd: &str) -> &str { +/Users/andrew/Programming/rtk/src/discover/registry.rs:423:pub fn split_command_chain(cmd: &str) -> Vec<&str> { +/Users/andrew/Programming/rtk/src/discover/registry.rs:511: fn test_classify_git_status() { +/Users/andrew/Programming/rtk/src/discover/registry.rs:524: fn test_classify_git_diff_cached() { +/Users/andrew/Programming/rtk/src/discover/registry.rs:537: fn test_classify_cargo_test_filter() { +/Users/andrew/Programming/rtk/src/discover/registry.rs:550: fn test_classify_npx_tsc() { +/Users/andrew/Programming/rtk/src/discover/registry.rs:563: fn test_classify_cat_file() { +/Users/andrew/Programming/rtk/src/discover/registry.rs:576: fn test_classify_grepai_search() { +/Users/andrew/Programming/rtk/src/discover/registry.rs:589: fn test_classify_plain_rgai() { +/Users/andrew/Programming/rtk/src/discover/registry.rs:602: fn test_classify_cd_ignored() { +/Users/andrew/Programming/rtk/src/discover/registry.rs:607: fn test_classify_rtk_already() { +/Users/andrew/Programming/rtk/src/discover/registry.rs:612: fn test_classify_echo_ignored() { +/Users/andrew/Programming/rtk/src/discover/registry.rs:620: fn test_classify_terraform_unsupported() { +/Users/andrew/Programming/rtk/src/discover/registry.rs:630: fn test_classify_env_prefix_stripped() { +/Users/andrew/Programming/rtk/src/discover/registry.rs:643: fn test_classify_sudo_stripped() { +/Users/andrew/Programming/rtk/src/discover/registry.rs:656: fn test_classify_cargo_check() { +/Users/andrew/Programming/rtk/src/discover/registry.rs:669: fn test_classify_cargo_check_all_targets() { +/Users/andrew/Programming/rtk/src/discover/registry.rs:682: fn test_classify_cargo_fmt_passthrough() { +/Users/andrew/Programming/rtk/src/discover/registry.rs:695: fn test_classify_cargo_clippy_savings() { +/Users/andrew/Programming/rtk/src/discover/registry.rs:708: fn test_patterns_rules_length_match() { +/Users/andrew/Programming/rtk/src/discover/registry.rs:717: fn test_registry_covers_all_cargo_subcommands() { +/Users/andrew/Programming/rtk/src/discover/registry.rs:730: fn test_registry_covers_all_git_subcommands() { +/Users/andrew/Programming/rtk/src/discover/registry.rs:745: fn test_split_chain_and() { +/Users/andrew/Programming/rtk/src/discover/registry.rs:750: fn test_split_chain_semicolon() { +/Users/andrew/Programming/rtk/src/discover/registry.rs:755: fn test_split_pipe_first_only() { +/Users/andrew/Programming/rtk/src/discover/registry.rs:760: fn test_split_single() { +/Users/andrew/Programming/rtk/src/discover/registry.rs:765: fn test_split_quoted_and() { +/Users/andrew/Programming/rtk/src/discover/registry.rs:773: fn test_split_heredoc_no_split() { +/Users/andrew/Programming/rtk/src/discover/provider.rs:26: fn discover_sessions( +/Users/andrew/Programming/rtk/src/discover/provider.rs:31: fn extract_commands(&self, path: &Path) -> Result>; +/Users/andrew/Programming/rtk/src/discover/provider.rs:38: fn projects_dir() -> Result { +/Users/andrew/Programming/rtk/src/discover/provider.rs:52: pub fn encode_project_path(path: &str) -> String { +/Users/andrew/Programming/rtk/src/discover/provider.rs:58: fn discover_sessions( +/Users/andrew/Programming/rtk/src/discover/provider.rs:119: fn extract_commands(&self, path: &Path) -> Result> { +/Users/andrew/Programming/rtk/src/discover/provider.rs:242: fn make_jsonl(lines: &[&str]) -> tempfile::NamedTempFile { +/Users/andrew/Programming/rtk/src/discover/provider.rs:252: fn test_extract_assistant_bash() { +/Users/andrew/Programming/rtk/src/discover/provider.rs:270: fn test_extract_non_bash_ignored() { +/Users/andrew/Programming/rtk/src/discover/provider.rs:281: fn test_extract_non_message_ignored() { +/Users/andrew/Programming/rtk/src/discover/provider.rs:291: fn test_extract_multiple_tools() { +/Users/andrew/Programming/rtk/src/discover/provider.rs:304: fn test_extract_malformed_line() { +/Users/andrew/Programming/rtk/src/discover/provider.rs:317: fn test_encode_project_path() { +/Users/andrew/Programming/rtk/src/discover/provider.rs:325: fn test_encode_project_path_trailing_slash() { +/Users/andrew/Programming/rtk/src/discover/provider.rs:333: fn test_match_project_filter() { +/Users/andrew/Programming/rtk/src/discover/provider.rs:340: fn test_extract_output_content() { +/Users/andrew/Programming/rtk/src/discover/provider.rs:359: fn test_extract_is_error_flag() { +/Users/andrew/Programming/rtk/src/discover/provider.rs:373: fn test_extract_sequence_ordering() { +/Users/andrew/Programming/rtk/src/discover/report.rs:15: pub fn as_str(&self) -> &'static str { +/Users/andrew/Programming/rtk/src/discover/report.rs:57: pub fn total_saveable_tokens(&self) -> usize { +/Users/andrew/Programming/rtk/src/discover/report.rs:64: pub fn total_supported_count(&self) -> usize { +/Users/andrew/Programming/rtk/src/discover/report.rs:70:pub fn format_text(report: &DiscoverReport, limit: usize, verbose: bool) -> String { +/Users/andrew/Programming/rtk/src/discover/report.rs:159:pub fn format_json(report: &DiscoverReport) -> String { +/Users/andrew/Programming/rtk/src/discover/report.rs:163:fn format_tokens(tokens: usize) -> String { +/Users/andrew/Programming/rtk/src/discover/report.rs:173:fn truncate_str(s: &str, max: usize) -> String { +/Users/andrew/Programming/rtk/src/discover/mod.rs:29:pub fn run( +/Users/andrew/Programming/rtk/src/discover/mod.rs:219:fn extract_subcmd(cmd: &str) -> &str { +/Users/andrew/Programming/rtk/src/discover/mod.rs:229:fn truncate_command(cmd: &str) -> String { +/Users/andrew/Programming/rtk/src/wget_cmd.rs:6:pub fn run(url: &str, args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/wget_cmd.rs:54:pub fn run_stdout(url: &str, args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/wget_cmd.rs:115:fn extract_filename_from_output(stderr: &str, url: &str, args: &[String]) -> String { +/Users/andrew/Programming/rtk/src/wget_cmd.rs:172:fn get_file_size(filename: &str) -> u64 { +/Users/andrew/Programming/rtk/src/wget_cmd.rs:176:fn format_size(bytes: u64) -> String { +/Users/andrew/Programming/rtk/src/wget_cmd.rs:191:fn compact_url(url: &str) -> String { +/Users/andrew/Programming/rtk/src/wget_cmd.rs:209:fn parse_error(stderr: &str, stdout: &str) -> String { +/Users/andrew/Programming/rtk/src/wget_cmd.rs:253:fn truncate_line(line: &str, max: usize) -> String { +/Users/andrew/Programming/rtk/src/npm_cmd.rs:5:pub fn run(args: &[String], verbose: u8, skip_env: bool) -> Result<()> { +/Users/andrew/Programming/rtk/src/npm_cmd.rs:46:fn filter_npm_output(output: &str) -> String { +/Users/andrew/Programming/rtk/src/npm_cmd.rs:85: fn test_filter_npm_output() { +/Users/andrew/Programming/rtk/src/npm_cmd.rs:104: fn test_filter_npm_output_empty() { +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:18:pub fn run(cmd: CargoCommand, args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:29:fn run_cargo_filtered(subcommand: &str, args: &[String], verbose: u8, filter_fn: F) -> Result<()> +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:52: let filtered = filter_fn(&raw); +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:69:fn run_build(args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:73:fn run_test(args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:77:fn run_clippy(args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:81:fn run_check(args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:85:fn run_install(args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:90:fn format_crate_info(name: &str, version: &str, fallback: &str) -> String { +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:101:fn filter_cargo_install(output: &str) -> String { +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:273:fn filter_cargo_build(output: &str) -> String { +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:379: fn parse_line(line: &str) -> Option { +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:420: fn merge(&mut self, other: &Self) { +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:432: fn format_compact(&self) -> String { +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:462:fn filter_cargo_test(output: &str) -> String { +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:580:fn filter_cargo_clippy(output: &str) -> String { +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:676:pub fn run_passthrough(args: &[OsString], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:704: fn test_filter_cargo_build_success() { +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:716: fn test_filter_cargo_build_errors() { +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:733: fn test_filter_cargo_test_all_pass() { +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:756: fn test_filter_cargo_test_failures() { +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:779: fn test_filter_cargo_test_multi_suite_all_pass() { +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:812: fn test_filter_cargo_test_multi_suite_with_failures() { +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:847: fn test_filter_cargo_test_all_suites_zero_tests() { +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:875: fn test_filter_cargo_test_with_ignored_and_filtered() { +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:895: fn test_filter_cargo_test_single_suite_compact() { +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:910: fn test_filter_cargo_test_regex_fallback() { +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:926: fn test_filter_cargo_clippy_clean() { +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:935: fn test_filter_cargo_clippy_warnings() { +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:946:16| pub fn run(a: i32, b: i32, c: i32, d: i32, e: i32, f: i32, g: i32, h: i32) {} +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:959: fn test_filter_cargo_install_success() { +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:983: fn test_filter_cargo_install_replace() { +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:997: fn test_filter_cargo_install_error() { +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:1016: fn test_filter_cargo_install_already_installed() { +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:1025: fn test_filter_cargo_install_up_to_date() { +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:1034: fn test_filter_cargo_install_empty_output() { +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:1041: fn test_filter_cargo_install_path_warning() { +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:1060: fn test_filter_cargo_install_multiple_errors() { +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:1089: fn test_filter_cargo_install_locking_and_blocking() { +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:1107: fn test_filter_cargo_install_from_path() { +/Users/andrew/Programming/rtk/src/cargo_cmd.rs:1119: fn test_format_crate_info() { +/Users/andrew/Programming/rtk/src/ccusage.rs:86:fn binary_exists() -> bool { +/Users/andrew/Programming/rtk/src/ccusage.rs:95:fn build_command() -> Option { +/Users/andrew/Programming/rtk/src/ccusage.rs:118:pub fn is_available() -> bool { +/Users/andrew/Programming/rtk/src/ccusage.rs:127:pub fn fetch(granularity: Granularity) -> Result>> { +/Users/andrew/Programming/rtk/src/ccusage.rs:176:fn parse_json(json: &str, granularity: Granularity) -> Result> { +/Users/andrew/Programming/rtk/src/ccusage.rs:222: fn test_parse_monthly_valid() { +/Users/andrew/Programming/rtk/src/ccusage.rs:247: fn test_parse_daily_valid() { +/Users/andrew/Programming/rtk/src/ccusage.rs:270: fn test_parse_weekly_valid() { +/Users/andrew/Programming/rtk/src/ccusage.rs:293: fn test_parse_malformed_json() { +/Users/andrew/Programming/rtk/src/ccusage.rs:300: fn test_parse_missing_required_fields() { +/Users/andrew/Programming/rtk/src/ccusage.rs:314: fn test_parse_default_cache_fields() { +/Users/andrew/Programming/rtk/src/ccusage.rs:335: fn test_is_available() { +/Users/andrew/Programming/rtk/src/go_cmd.rs:34:pub fn run_test(args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/go_cmd.rs:85:pub fn run_build(args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/go_cmd.rs:128:pub fn run_vet(args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/go_cmd.rs:171:pub fn run_other(args: &[OsString], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/go_cmd.rs:217:fn filter_go_test_json(output: &str) -> String { +/Users/andrew/Programming/rtk/src/go_cmd.rs:341:fn filter_go_build(output: &str) -> String { +/Users/andrew/Programming/rtk/src/go_cmd.rs:384:fn filter_go_vet(output: &str) -> String { +/Users/andrew/Programming/rtk/src/go_cmd.rs:416:fn compact_package_name(package: &str) -> String { +/Users/andrew/Programming/rtk/src/go_cmd.rs:430: fn test_filter_go_test_all_pass() { +/Users/andrew/Programming/rtk/src/go_cmd.rs:443: fn test_filter_go_test_with_failures() { +/Users/andrew/Programming/rtk/src/go_cmd.rs:457: fn test_filter_go_build_success() { +/Users/andrew/Programming/rtk/src/go_cmd.rs:465: fn test_filter_go_build_errors() { +/Users/andrew/Programming/rtk/src/go_cmd.rs:477: fn test_filter_go_vet_no_issues() { +/Users/andrew/Programming/rtk/src/go_cmd.rs:485: fn test_filter_go_vet_with_issues() { +/Users/andrew/Programming/rtk/src/go_cmd.rs:496: fn test_compact_package_name() { +/Users/andrew/Programming/rtk/src/config.rs:24: fn default() -> Self { +/Users/andrew/Programming/rtk/src/config.rs:41: fn default() -> Self { +/Users/andrew/Programming/rtk/src/config.rs:57: fn default() -> Self { +/Users/andrew/Programming/rtk/src/config.rs:73: pub fn load() -> Result { +/Users/andrew/Programming/rtk/src/config.rs:85: pub fn save(&self) -> Result<()> { +/Users/andrew/Programming/rtk/src/config.rs:97: pub fn create_default() -> Result { +/Users/andrew/Programming/rtk/src/config.rs:104:fn get_config_path() -> Result { +/Users/andrew/Programming/rtk/src/config.rs:109:pub fn show_config() -> Result<()> { +/Users/andrew/Programming/rtk/src/lint_cmd.rs:28:pub fn run(args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/lint_cmd.rs:100:fn filter_eslint_json(output: &str) -> String { +/Users/andrew/Programming/rtk/src/lint_cmd.rs:192:fn filter_generic_lint(output: &str) -> String { +/Users/andrew/Programming/rtk/src/lint_cmd.rs:229:fn compact_path(path: &str) -> String { +/Users/andrew/Programming/rtk/src/lint_cmd.rs:249: fn test_filter_eslint_json() { +/Users/andrew/Programming/rtk/src/lint_cmd.rs:296: fn test_compact_path() { +/Users/andrew/Programming/rtk/src/curl_cmd.rs:7:pub fn run(args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/curl_cmd.rs:50:fn filter_curl_output(output: &str) -> String { +/Users/andrew/Programming/rtk/src/curl_cmd.rs:88: fn test_filter_curl_json() { +/Users/andrew/Programming/rtk/src/curl_cmd.rs:97: fn test_filter_curl_json_array() { +/Users/andrew/Programming/rtk/src/curl_cmd.rs:104: fn test_filter_curl_non_json() { +/Users/andrew/Programming/rtk/src/curl_cmd.rs:112: fn test_filter_curl_long_output() { +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:19:pub fn run(cmd: PrismaCommand, args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:28:fn create_prisma_command() -> Command { +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:44:fn run_generate(args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:79:fn run_migrate(subcommand: MigrateSubcommand, args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:135:fn run_db_push(args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:169:fn filter_prisma_generate(output: &str) -> String { +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:228:fn filter_migrate_dev(output: &str) -> String { +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:300:fn filter_migrate_status(output: &str) -> String { +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:334:fn filter_migrate_deploy(output: &str) -> String { +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:362:fn filter_db_push(output: &str) -> String { +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:393:fn extract_number(line: &str) -> Option { +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:399:fn extract_table_name(line: &str) -> Option { +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:416:fn extract_index_name(line: &str) -> Option { +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:437: fn test_filter_generate() { +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:457: fn test_filter_migrate_dev() { +/Users/andrew/Programming/rtk/src/prisma_cmd.rs:478: fn test_extract_number() { +/Users/andrew/Programming/rtk/src/cc_economics.rs:54: fn new(label: &str) -> Self { +/Users/andrew/Programming/rtk/src/cc_economics.rs:76: fn set_ccusage(&mut self, metrics: &ccusage::CcusageMetrics) { +/Users/andrew/Programming/rtk/src/cc_economics.rs:91: fn set_rtk_from_day(&mut self, stats: &DayStats) { +/Users/andrew/Programming/rtk/src/cc_economics.rs:97: fn set_rtk_from_week(&mut self, stats: &WeekStats) { +/Users/andrew/Programming/rtk/src/cc_economics.rs:103: fn set_rtk_from_month(&mut self, stats: &MonthStats) { +/Users/andrew/Programming/rtk/src/cc_economics.rs:115: fn compute_weighted_metrics(&mut self) { +/Users/andrew/Programming/rtk/src/cc_economics.rs:141: fn compute_dual_metrics(&mut self) { +/Users/andrew/Programming/rtk/src/cc_economics.rs:184:pub fn run( +/Users/andrew/Programming/rtk/src/cc_economics.rs:203:fn merge_daily(cc: Option>, rtk: Vec) -> Vec { +/Users/andrew/Programming/rtk/src/cc_economics.rs:233:fn merge_weekly(cc: Option>, rtk: Vec) -> Vec { +/Users/andrew/Programming/rtk/src/cc_economics.rs:271:fn merge_monthly(cc: Option>, rtk: Vec) -> Vec { +/Users/andrew/Programming/rtk/src/cc_economics.rs:304:fn convert_saturday_to_monday(saturday: &str) -> Option { +/Users/andrew/Programming/rtk/src/cc_economics.rs:314:fn compute_totals(periods: &[PeriodEconomics]) -> Totals { +/Users/andrew/Programming/rtk/src/cc_economics.rs:402:fn display_text( +/Users/andrew/Programming/rtk/src/cc_economics.rs:429:fn display_summary(tracker: &Tracker, verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/cc_economics.rs:544:fn display_daily(tracker: &Tracker, verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/cc_economics.rs:558:fn display_weekly(tracker: &Tracker, verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/cc_economics.rs:572:fn display_monthly(tracker: &Tracker, verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/cc_economics.rs:586:fn print_period_table(periods: &[PeriodEconomics], verbose: u8) { +/Users/andrew/Programming/rtk/src/cc_economics.rs:665:fn export_json( +/Users/andrew/Programming/rtk/src/cc_economics.rs:724:fn export_csv( +/Users/andrew/Programming/rtk/src/cc_economics.rs:773:fn print_csv_row(p: &PeriodEconomics) { +/Users/andrew/Programming/rtk/src/cc_economics.rs:834: fn test_convert_saturday_to_monday() { +/Users/andrew/Programming/rtk/src/cc_economics.rs:846: fn test_period_economics_new() { +/Users/andrew/Programming/rtk/src/cc_economics.rs:854: fn test_compute_dual_metrics_with_data() { +/Users/andrew/Programming/rtk/src/cc_economics.rs:877: fn test_compute_dual_metrics_zero_tokens() { +/Users/andrew/Programming/rtk/src/cc_economics.rs:896: fn test_compute_dual_metrics_no_ccusage_data() { +/Users/andrew/Programming/rtk/src/cc_economics.rs:910: fn test_merge_monthly_both_present() { +/Users/andrew/Programming/rtk/src/cc_economics.rs:942: fn test_merge_monthly_only_ccusage() { +/Users/andrew/Programming/rtk/src/cc_economics.rs:962: fn test_merge_monthly_only_rtk() { +/Users/andrew/Programming/rtk/src/cc_economics.rs:981: fn test_merge_monthly_sorted() { +/Users/andrew/Programming/rtk/src/cc_economics.rs:1012: fn test_compute_weighted_input_cpt() { +/Users/andrew/Programming/rtk/src/cc_economics.rs:1037: fn test_compute_weighted_metrics_zero_tokens() { +/Users/andrew/Programming/rtk/src/cc_economics.rs:1053: fn test_compute_weighted_metrics_no_cache() { +/Users/andrew/Programming/rtk/src/cc_economics.rs:1078: fn test_set_ccusage_stores_per_type_tokens() { +/Users/andrew/Programming/rtk/src/cc_economics.rs:1100: fn test_compute_totals() { +/Users/andrew/Programming/rtk/src/find_cmd.rs:8:fn glob_match(pattern: &str, name: &str) -> bool { +/Users/andrew/Programming/rtk/src/find_cmd.rs:12:fn glob_match_inner(pat: &[u8], name: &[u8]) -> bool { +/Users/andrew/Programming/rtk/src/find_cmd.rs:26:pub fn run( +/Users/andrew/Programming/rtk/src/find_cmd.rs:212: fn glob_match_star_rs() { +/Users/andrew/Programming/rtk/src/find_cmd.rs:220: fn glob_match_star_all() { +/Users/andrew/Programming/rtk/src/find_cmd.rs:227: fn glob_match_question_mark() { +/Users/andrew/Programming/rtk/src/find_cmd.rs:233: fn glob_match_exact() { +/Users/andrew/Programming/rtk/src/find_cmd.rs:239: fn glob_match_complex() { +/Users/andrew/Programming/rtk/src/find_cmd.rs:248: fn dot_becomes_star() { +/Users/andrew/Programming/rtk/src/find_cmd.rs:257: fn find_rs_files_in_src() { +/Users/andrew/Programming/rtk/src/find_cmd.rs:264: fn find_dot_pattern_works() { +/Users/andrew/Programming/rtk/src/find_cmd.rs:271: fn find_no_matches() { +/Users/andrew/Programming/rtk/src/find_cmd.rs:277: fn find_respects_max() { +/Users/andrew/Programming/rtk/src/find_cmd.rs:284: fn find_gitignored_excluded() { +/Users/andrew/Programming/rtk/src/gain.rs:7:pub fn run( +/Users/andrew/Programming/rtk/src/gain.rs:160:fn print_ascii_graph(data: &[(String, usize)]) { +/Users/andrew/Programming/rtk/src/gain.rs:190:fn print_daily_full(tracker: &Tracker) -> Result<()> { +/Users/andrew/Programming/rtk/src/gain.rs:196:fn print_weekly(tracker: &Tracker) -> Result<()> { +/Users/andrew/Programming/rtk/src/gain.rs:202:fn print_monthly(tracker: &Tracker) -> Result<()> { +/Users/andrew/Programming/rtk/src/gain.rs:230:fn export_json( +/Users/andrew/Programming/rtk/src/gain.rs:274:fn export_csv( +/Users/andrew/Programming/rtk/src/golangci_cmd.rs:34:pub fn run(args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/golangci_cmd.rs:88:fn filter_golangci_json(output: &str) -> String { +/Users/andrew/Programming/rtk/src/golangci_cmd.rs:179:fn compact_path(path: &str) -> String { +/Users/andrew/Programming/rtk/src/golangci_cmd.rs:200: fn test_filter_golangci_no_issues() { +/Users/andrew/Programming/rtk/src/golangci_cmd.rs:208: fn test_filter_golangci_with_issues() { +/Users/andrew/Programming/rtk/src/golangci_cmd.rs:239: fn test_compact_path() { +/Users/andrew/Programming/rtk/src/git.rs:22:pub fn run(cmd: GitCommand, args: &[String], max_lines: Option, verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/git.rs:39:fn run_diff(args: &[String], max_lines: Option, verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/git.rs:126:fn run_show(args: &[String], max_lines: Option, verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/git.rs:232:pub(crate) fn compact_diff(diff: &str, max_lines: usize) -> String { +/Users/andrew/Programming/rtk/src/git.rs:298:fn run_log(args: &[String], _max_lines: Option, verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/git.rs:375:fn filter_log_output(output: &str, limit: usize) -> String { +/Users/andrew/Programming/rtk/src/git.rs:394:fn format_status_output(porcelain: &str) -> String { +/Users/andrew/Programming/rtk/src/git.rs:490:fn filter_status_with_args(output: &str) -> String { +/Users/andrew/Programming/rtk/src/git.rs:526:fn run_status(args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/git.rs:582:fn run_add(args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/git.rs:654:fn run_commit(message: &str, verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/git.rs:718:fn run_push(args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/git.rs:779:fn run_pull(args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/git.rs:864:fn run_branch(args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/git.rs:938:fn filter_branch_output(output: &str) -> String { +/Users/andrew/Programming/rtk/src/git.rs:992:fn run_fetch(args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/git.rs:1036:fn run_stash(subcommand: Option<&str>, args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/git.rs:1153:fn filter_stash_list(output: &str) -> String { +/Users/andrew/Programming/rtk/src/git.rs:1174:fn run_worktree(args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/git.rs:1237:fn filter_worktree_list(output: &str) -> String { +/Users/andrew/Programming/rtk/src/git.rs:1265:pub fn run_passthrough(args: &[OsString], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/git.rs:1293: fn test_compact_diff() { +/Users/andrew/Programming/rtk/src/git.rs:1298: fn main() { +/Users/andrew/Programming/rtk/src/git.rs:1308: fn test_filter_branch_output() { +/Users/andrew/Programming/rtk/src/git.rs:1320: fn test_filter_branch_no_remotes() { +/Users/andrew/Programming/rtk/src/git.rs:1329: fn test_filter_stash_list() { +/Users/andrew/Programming/rtk/src/git.rs:1338: fn test_filter_worktree_list() { +/Users/andrew/Programming/rtk/src/git.rs:1348: fn test_format_status_output_clean() { +/Users/andrew/Programming/rtk/src/git.rs:1355: fn test_format_status_output_modified_files() { +/Users/andrew/Programming/rtk/src/git.rs:1367: fn test_format_status_output_untracked_files() { +/Users/andrew/Programming/rtk/src/git.rs:1379: fn test_format_status_output_mixed_changes() { +/Users/andrew/Programming/rtk/src/git.rs:1398: fn test_format_status_output_truncation() { +/Users/andrew/Programming/rtk/src/git.rs:1419: fn test_run_passthrough_accepts_args() { +/Users/andrew/Programming/rtk/src/git.rs:1426: fn test_filter_log_output() { +/Users/andrew/Programming/rtk/src/git.rs:1435: fn test_filter_log_output_truncate_long() { +/Users/andrew/Programming/rtk/src/git.rs:1444: fn test_filter_log_output_cap_lines() { +/Users/andrew/Programming/rtk/src/git.rs:1454: fn test_filter_status_with_args() { +/Users/andrew/Programming/rtk/src/git.rs:1476: fn test_filter_status_with_args_clean() { +/Users/andrew/Programming/rtk/src/git.rs:1483: fn test_filter_log_output_multibyte() { +/Users/andrew/Programming/rtk/src/git.rs:1495: fn test_filter_log_output_emoji() { +/Users/andrew/Programming/rtk/src/git.rs:1503: fn test_format_status_output_thai_filename() { +/Users/andrew/Programming/rtk/src/git.rs:1513: fn test_format_status_output_emoji_filename() { +/Users/andrew/Programming/rtk/src/runner.rs:7:pub fn run_err(command: &str, verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/runner.rs:58:pub fn run_test(command: &str, verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/runner.rs:90:fn filter_errors(output: &str) -> String { +/Users/andrew/Programming/rtk/src/runner.rs:147:fn extract_test_summary(output: &str, command: &str) -> String { +/Users/andrew/Programming/rtk/src/runner.rs:249: fn test_filter_errors() { +/Users/andrew/Programming/rtk/src/deps.rs:8:pub fn run(path: &Path, verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/deps.rs:74:fn summarize_cargo_str(path: &Path) -> Result { +/Users/andrew/Programming/rtk/src/deps.rs:127:fn summarize_package_json_str(path: &Path) -> Result { +/Users/andrew/Programming/rtk/src/deps.rs:163:fn summarize_requirements_str(path: &Path) -> Result { +/Users/andrew/Programming/rtk/src/deps.rs:191:fn summarize_pyproject_str(path: &Path) -> Result { +/Users/andrew/Programming/rtk/src/deps.rs:227:fn summarize_gomod_str(path: &Path) -> Result { +/Users/andrew/Programming/rtk/src/parser/error.rs:39: fn from(err: serde_json::Error) -> Self { +/Users/andrew/Programming/rtk/src/parser/formatter.rs:16: pub fn from_verbosity(verbosity: u8) -> Self { +/Users/andrew/Programming/rtk/src/parser/formatter.rs:28: fn format_compact(&self) -> String; +/Users/andrew/Programming/rtk/src/parser/formatter.rs:31: fn format_verbose(&self) -> String; +/Users/andrew/Programming/rtk/src/parser/formatter.rs:34: fn format_ultra(&self) -> String; +/Users/andrew/Programming/rtk/src/parser/formatter.rs:37: fn format(&self, mode: FormatMode) -> String { +/Users/andrew/Programming/rtk/src/parser/formatter.rs:47: fn format_compact(&self) -> String { +/Users/andrew/Programming/rtk/src/parser/formatter.rs:75: fn format_verbose(&self) -> String { +/Users/andrew/Programming/rtk/src/parser/formatter.rs:106: fn format_ultra(&self) -> String { +/Users/andrew/Programming/rtk/src/parser/formatter.rs:118: fn format_compact(&self) -> String { +/Users/andrew/Programming/rtk/src/parser/formatter.rs:154: fn format_verbose(&self) -> String { +/Users/andrew/Programming/rtk/src/parser/formatter.rs:187: fn format_ultra(&self) -> String { +/Users/andrew/Programming/rtk/src/parser/formatter.rs:196: fn format_compact(&self) -> String { +/Users/andrew/Programming/rtk/src/parser/formatter.rs:224: fn format_verbose(&self) -> String { +/Users/andrew/Programming/rtk/src/parser/formatter.rs:253: fn format_ultra(&self) -> String { +/Users/andrew/Programming/rtk/src/parser/formatter.rs:259: fn format_compact(&self) -> String { +/Users/andrew/Programming/rtk/src/parser/formatter.rs:286: fn format_verbose(&self) -> String { +/Users/andrew/Programming/rtk/src/parser/formatter.rs:326: fn format_ultra(&self) -> String { +/Users/andrew/Programming/rtk/src/parser/README.md:52: fn parse(input: &str) -> ParseResult { +/Users/andrew/Programming/rtk/src/parser/README.md:86:pub fn run_vitest(args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/parser/README.md:183:fn run_vitest(args: &[String]) -> Result<()> { +/Users/andrew/Programming/rtk/src/parser/README.md:193:fn run_vitest(args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/parser/README.md:229:fn test_vitest_json_parsing() { +/Users/andrew/Programming/rtk/src/parser/README.md:237:fn test_vitest_regex_fallback() { +/Users/andrew/Programming/rtk/src/parser/mod.rs:32: pub fn unwrap(self) -> T { +/Users/andrew/Programming/rtk/src/parser/mod.rs:41: pub fn tier(&self) -> u8 { +/Users/andrew/Programming/rtk/src/parser/mod.rs:50: pub fn is_ok(&self) -> bool { +/Users/andrew/Programming/rtk/src/parser/mod.rs:55: pub fn map(self, f: F) -> ParseResult +/Users/andrew/Programming/rtk/src/parser/mod.rs:67: pub fn warnings(&self) -> Vec { +/Users/andrew/Programming/rtk/src/parser/mod.rs:85: fn parse(input: &str) -> ParseResult; +/Users/andrew/Programming/rtk/src/parser/mod.rs:88: fn parse_with_tier(input: &str, max_tier: u8) -> ParseResult { +/Users/andrew/Programming/rtk/src/parser/mod.rs:99:pub fn truncate_output(output: &str, max_chars: usize) -> String { +/Users/andrew/Programming/rtk/src/parser/mod.rs:115:pub fn emit_degradation_warning(tool: &str, reason: &str) { +/Users/andrew/Programming/rtk/src/parser/mod.rs:120:pub fn emit_passthrough_warning(tool: &str, reason: &str) { +/Users/andrew/Programming/rtk/src/parser/mod.rs:134:pub fn extract_json_object(input: &str) -> Option<&str> { +/Users/andrew/Programming/rtk/src/parser/mod.rs:195: fn test_parse_result_tier() { +/Users/andrew/Programming/rtk/src/parser/mod.rs:211: fn test_parse_result_map() { +/Users/andrew/Programming/rtk/src/parser/mod.rs:225: fn test_truncate_output() { +/Users/andrew/Programming/rtk/src/parser/mod.rs:236: fn test_truncate_output_multibyte() { +/Users/andrew/Programming/rtk/src/parser/mod.rs:247: fn test_truncate_output_emoji() { +/Users/andrew/Programming/rtk/src/parser/mod.rs:254: fn test_extract_json_object_clean() { +/Users/andrew/Programming/rtk/src/parser/mod.rs:261: fn test_extract_json_object_with_pnpm_prefix() { +/Users/andrew/Programming/rtk/src/parser/mod.rs:275: fn test_extract_json_object_with_dotenv_prefix() { +/Users/andrew/Programming/rtk/src/parser/mod.rs:287: fn test_extract_json_object_nested_braces() { +/Users/andrew/Programming/rtk/src/parser/mod.rs:298: fn test_extract_json_object_no_json() { +/Users/andrew/Programming/rtk/src/parser/mod.rs:305: fn test_extract_json_object_string_with_braces() { +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:51: fn parse(input: &str) -> ParseResult { +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:87:fn collect_dependencies( +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:115:fn extract_list_text(output: &str) -> Option { +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:168: fn parse(input: &str) -> ParseResult { +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:214:fn extract_outdated_text(output: &str) -> Option { +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:264:fn is_valid_package_name(name: &str) -> bool { +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:286:pub fn run(cmd: PnpmCommand, args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:294:fn run_list(depth: usize, args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:350:fn run_outdated(args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:401:fn run_install(packages: &[String], args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:453:fn filter_pnpm_install(output: &str) -> String { +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:492:pub fn run_passthrough(args: &[OsString], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:520: fn test_pnpm_list_parser_json() { +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:541: fn test_pnpm_outdated_parser_json() { +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:560: fn test_package_name_validation() { +/Users/andrew/Programming/rtk/src/pnpm_cmd.rs:568: fn test_run_passthrough_accepts_args() { +/Users/andrew/Programming/rtk/src/tree.rs:43:pub fn run(args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/tree.rs:105:fn filter_tree_output(raw: &str) -> String { +/Users/andrew/Programming/rtk/src/tree.rs:141: fn test_filter_removes_summary() { +/Users/andrew/Programming/rtk/src/tree.rs:151: fn test_filter_preserves_structure() { +/Users/andrew/Programming/rtk/src/tree.rs:162: fn test_filter_handles_empty() { +/Users/andrew/Programming/rtk/src/tree.rs:169: fn test_filter_removes_trailing_empty_lines() { +/Users/andrew/Programming/rtk/src/tree.rs:176: fn test_filter_summary_variations() { +/Users/andrew/Programming/rtk/src/tree.rs:199: fn test_noise_dirs_constant() { +/Users/andrew/Programming/rtk/src/log_cmd.rs:10:pub fn run_file(file: &Path, verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/log_cmd.rs:30:pub fn run_stdin(_verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/log_cmd.rs:49:pub fn run_stdin_str(content: &str) -> String { +/Users/andrew/Programming/rtk/src/log_cmd.rs:53:fn analyze_logs(content: &str) -> String { +/Users/andrew/Programming/rtk/src/log_cmd.rs:202:fn normalize_log_line( +/Users/andrew/Programming/rtk/src/log_cmd.rs:223: fn test_analyze_logs() { +/Users/andrew/Programming/rtk/src/log_cmd.rs:237: fn test_analyze_logs_multibyte() { +/Users/andrew/Programming/rtk/src/ruff_cmd.rs:31:pub fn run(args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/ruff_cmd.rs:115:fn filter_ruff_check_json(output: &str) -> String { +/Users/andrew/Programming/rtk/src/ruff_cmd.rs:217:fn filter_ruff_format(output: &str) -> String { +/Users/andrew/Programming/rtk/src/ruff_cmd.rs:303:fn compact_path(path: &str) -> String { +/Users/andrew/Programming/rtk/src/ruff_cmd.rs:324: fn test_filter_ruff_check_no_issues() { +/Users/andrew/Programming/rtk/src/ruff_cmd.rs:332: fn test_filter_ruff_check_with_issues() { +/Users/andrew/Programming/rtk/src/ruff_cmd.rs:370: fn test_filter_ruff_format_all_formatted() { +/Users/andrew/Programming/rtk/src/ruff_cmd.rs:378: fn test_filter_ruff_format_needs_formatting() { +/Users/andrew/Programming/rtk/src/ruff_cmd.rs:390: fn test_compact_path() { +/Users/andrew/Programming/rtk/src/grep_cmd.rs:7:pub fn run( +/Users/andrew/Programming/rtk/src/grep_cmd.rs:120:fn clean_line(line: &str, max_len: usize, context_only: bool, pattern: &str) -> String { +/Users/andrew/Programming/rtk/src/grep_cmd.rs:168:fn compact_path(path: &str) -> String { +/Users/andrew/Programming/rtk/src/grep_cmd.rs:191: fn test_clean_line() { +/Users/andrew/Programming/rtk/src/grep_cmd.rs:199: fn test_compact_path() { +/Users/andrew/Programming/rtk/src/grep_cmd.rs:206: fn test_extra_args_accepted() { +/Users/andrew/Programming/rtk/src/grep_cmd.rs:214: fn test_clean_line_multibyte() { +/Users/andrew/Programming/rtk/src/grep_cmd.rs:223: fn test_clean_line_emoji() { +/Users/andrew/Programming/rtk/src/json_cmd.rs:9:pub fn run(file: &Path, max_depth: usize, verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/json_cmd.rs:31:pub fn run_stdin(max_depth: usize, verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/json_cmd.rs:52:pub fn filter_json_string(json_str: &str, max_depth: usize) -> Result { +/Users/andrew/Programming/rtk/src/json_cmd.rs:57:fn extract_schema(value: &Value, depth: usize, max_depth: usize) -> String { +/Users/andrew/Programming/rtk/src/json_cmd.rs:151: fn test_extract_schema_simple() { +/Users/andrew/Programming/rtk/src/json_cmd.rs:160: fn test_extract_schema_array() { +/Users/andrew/Programming/rtk/src/read.rs:7:pub fn run( +/Users/andrew/Programming/rtk/src/read.rs:73:pub fn run_stdin( +/Users/andrew/Programming/rtk/src/read.rs:135:fn format_with_line_numbers(content: &str) -> String { +/Users/andrew/Programming/rtk/src/read.rs:152: fn test_read_rust_file() -> Result<()> { +/Users/andrew/Programming/rtk/src/read.rs:157:fn main() {{ +/Users/andrew/Programming/rtk/src/read.rs:168: fn test_stdin_support_signature() { +/Users/andrew/Programming/rtk/src/tsc_cmd.rs:8:pub fn run(args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/tsc_cmd.rs:58:fn filter_tsc_output(output: &str) -> String { +/Users/andrew/Programming/rtk/src/tsc_cmd.rs:180: fn test_filter_tsc_output() { +/Users/andrew/Programming/rtk/src/tsc_cmd.rs:198: fn test_every_error_message_shown() { +/Users/andrew/Programming/rtk/src/tsc_cmd.rs:215: fn test_continuation_lines_preserved() { +/Users/andrew/Programming/rtk/src/tsc_cmd.rs:228: fn test_no_file_limit() { +/Users/andrew/Programming/rtk/src/tsc_cmd.rs:249: fn test_filter_no_errors() { +/Users/andrew/Programming/rtk/src/vitest_cmd.rs:53: fn parse(input: &str) -> ParseResult { +/Users/andrew/Programming/rtk/src/vitest_cmd.rs:100:fn extract_failures_from_json(json: &VitestJsonOutput) -> Vec { +/Users/andrew/Programming/rtk/src/vitest_cmd.rs:121:fn extract_stats_regex(output: &str) -> Option { +/Users/andrew/Programming/rtk/src/vitest_cmd.rs:178:fn extract_failures_regex(output: &str) -> Vec { +/Users/andrew/Programming/rtk/src/vitest_cmd.rs:216:pub fn run(cmd: VitestCommand, args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/vitest_cmd.rs:222:fn run_vitest(args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/vitest_cmd.rs:276: fn test_vitest_parser_json() { +/Users/andrew/Programming/rtk/src/vitest_cmd.rs:299: fn test_vitest_parser_regex_fallback() { +/Users/andrew/Programming/rtk/src/vitest_cmd.rs:316: fn test_vitest_parser_passthrough() { +/Users/andrew/Programming/rtk/src/vitest_cmd.rs:324: fn test_strip_ansi() { +/Users/andrew/Programming/rtk/src/vitest_cmd.rs:332: fn test_vitest_parser_with_pnpm_prefix() { +/Users/andrew/Programming/rtk/src/vitest_cmd.rs:350: fn test_vitest_parser_with_dotenv_prefix() { +/Users/andrew/Programming/rtk/src/vitest_cmd.rs:368: fn test_vitest_parser_with_nested_json() { +/Users/andrew/Programming/rtk/src/tracking.rs:223: pub fn new() -> Result { +/Users/andrew/Programming/rtk/src/tracking.rs:280: pub fn record( +/Users/andrew/Programming/rtk/src/tracking.rs:314: fn cleanup_old(&self) -> Result<()> { +/Users/andrew/Programming/rtk/src/tracking.rs:342: pub fn get_summary(&self) -> Result { +/Users/andrew/Programming/rtk/src/tracking.rs:399: fn get_by_command(&self) -> Result> { +/Users/andrew/Programming/rtk/src/tracking.rs:421: fn get_by_day(&self) -> Result> { +/Users/andrew/Programming/rtk/src/tracking.rs:457: pub fn get_all_days(&self) -> Result> { +/Users/andrew/Programming/rtk/src/tracking.rs:522: pub fn get_by_week(&self) -> Result> { +/Users/andrew/Programming/rtk/src/tracking.rs:589: pub fn get_by_month(&self) -> Result> { +/Users/andrew/Programming/rtk/src/tracking.rs:657: pub fn get_recent(&self, limit: usize) -> Result> { +/Users/andrew/Programming/rtk/src/tracking.rs:680:fn get_db_path() -> Result { +/Users/andrew/Programming/rtk/src/tracking.rs:717:pub fn estimate_tokens(text: &str) -> usize { +/Users/andrew/Programming/rtk/src/tracking.rs:759: pub fn start() -> Self { +/Users/andrew/Programming/rtk/src/tracking.rs:789: pub fn track(&self, original_cmd: &str, rtk_cmd: &str, input: &str, output: &str) { +/Users/andrew/Programming/rtk/src/tracking.rs:825: pub fn track_passthrough(&self, original_cmd: &str, rtk_cmd: &str) { +/Users/andrew/Programming/rtk/src/tracking.rs:848:pub fn args_display(args: &[OsString]) -> String { +/Users/andrew/Programming/rtk/src/tracking.rs:881:pub fn track(original_cmd: &str, rtk_cmd: &str, input: &str, output: &str) { +/Users/andrew/Programming/rtk/src/tracking.rs:896: fn test_estimate_tokens() { +/Users/andrew/Programming/rtk/src/tracking.rs:906: fn test_args_display() { +/Users/andrew/Programming/rtk/src/tracking.rs:917: fn test_tracker_record_and_recent() { +/Users/andrew/Programming/rtk/src/tracking.rs:941: fn test_track_passthrough_no_dilution() { +/Users/andrew/Programming/rtk/src/tracking.rs:985: fn test_timed_execution_records_time() { +/Users/andrew/Programming/rtk/src/tracking.rs:998: fn test_timed_execution_passthrough() { +/Users/andrew/Programming/rtk/src/tracking.rs:1017: fn test_custom_db_path_env() { +/Users/andrew/Programming/rtk/src/tracking.rs:1031: fn test_default_db_path() { +/Users/andrew/Programming/rtk/src/main.rs:825:fn main() -> Result<()> { +/Users/andrew/Programming/rtk/src/main.rs:1447:fn normalize_rgai_args(mut query_parts: Vec, mut path: String) -> (String, String) { +/Users/andrew/Programming/rtk/src/main.rs:1460:fn looks_like_path_token(token: &str) -> bool { +/Users/andrew/Programming/rtk/src/main.rs:1473: fn normalize_rgai_keeps_multiword_query() { +/Users/andrew/Programming/rtk/src/main.rs:1483: fn normalize_rgai_supports_old_positional_path() { +/Users/andrew/Programming/rtk/src/main.rs:1493: fn normalize_rgai_does_not_treat_plain_word_as_path() { +/Users/andrew/Programming/rtk/src/init.rs:176:pub fn run( +/Users/andrew/Programming/rtk/src/init.rs:192:fn prepare_hook_paths() -> Result<(PathBuf, PathBuf)> { +/Users/andrew/Programming/rtk/src/init.rs:203:fn ensure_hook_installed(hook_path: &Path, verbose: u8) -> Result { +/Users/andrew/Programming/rtk/src/init.rs:239:fn write_if_changed(path: &Path, content: &str, name: &str, verbose: u8) -> Result { +/Users/andrew/Programming/rtk/src/init.rs:269:fn atomic_write(path: &Path, content: &str) -> Result<()> { +/Users/andrew/Programming/rtk/src/init.rs:300:fn prompt_user_consent(settings_path: &Path) -> Result { +/Users/andrew/Programming/rtk/src/init.rs:323:fn print_manual_instructions(hook_path: &Path) { +/Users/andrew/Programming/rtk/src/init.rs:338:fn remove_hook_from_json(root: &mut serde_json::Value) -> bool { +/Users/andrew/Programming/rtk/src/init.rs:369:fn remove_hook_from_settings(verbose: u8) -> Result { +/Users/andrew/Programming/rtk/src/init.rs:412:pub fn uninstall(global: bool, verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/init.rs:480:fn patch_settings_json(hook_path: &Path, mode: PatchMode, verbose: u8) -> Result { +/Users/andrew/Programming/rtk/src/init.rs:559:fn clean_double_blanks(content: &str) -> String { +/Users/andrew/Programming/rtk/src/init.rs:592:fn insert_hook_entry(root: &mut serde_json::Value, hook_command: &str) { +/Users/andrew/Programming/rtk/src/init.rs:628:fn hook_already_present(root: &serde_json::Value, hook_command: &str) -> bool { +/Users/andrew/Programming/rtk/src/init.rs:652:fn run_default_mode(_global: bool, _patch_mode: PatchMode, _verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/init.rs:660:fn run_default_mode(global: bool, patch_mode: PatchMode, verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/init.rs:715:fn run_hook_only_mode(_global: bool, _patch_mode: PatchMode, _verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/init.rs:720:fn run_hook_only_mode(global: bool, patch_mode: PatchMode, verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/init.rs:760:fn run_claude_md_mode(global: bool, verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/init.rs:839:fn upsert_rtk_block(content: &str, block: &str) -> (String, RtkBlockUpsert) { +/Users/andrew/Programming/rtk/src/init.rs:882:fn patch_claude_md(path: &Path, verbose: u8) -> Result { +/Users/andrew/Programming/rtk/src/init.rs:931:fn remove_rtk_block(content: &str) -> (String, bool) { +/Users/andrew/Programming/rtk/src/init.rs:969:fn resolve_claude_dir() -> Result { +/Users/andrew/Programming/rtk/src/init.rs:976:pub fn show_config() -> Result<()> { +/Users/andrew/Programming/rtk/src/init.rs:1096: fn test_init_mentions_all_top_level_commands() { +/Users/andrew/Programming/rtk/src/init.rs:1123: fn test_init_has_version_marker() { +/Users/andrew/Programming/rtk/src/init.rs:1131: fn test_hook_has_guards() { +/Users/andrew/Programming/rtk/src/init.rs:1144: fn test_migration_removes_old_block() { +/Users/andrew/Programming/rtk/src/init.rs:1161: fn test_migration_warns_on_missing_end_marker() { +/Users/andrew/Programming/rtk/src/init.rs:1170: fn test_default_mode_creates_hook_and_rtk_md() { +/Users/andrew/Programming/rtk/src/init.rs:1189: fn test_claude_md_mode_creates_full_injection() { +/Users/andrew/Programming/rtk/src/init.rs:1199: fn test_search_priority_policy_in_init_and_slim_templates() { +/Users/andrew/Programming/rtk/src/init.rs:1212: fn test_files_search_examples_prioritize_rgai_before_grep() { +/Users/andrew/Programming/rtk/src/init.rs:1226: fn test_upsert_rtk_block_appends_when_missing() { +/Users/andrew/Programming/rtk/src/init.rs:1235: fn test_upsert_rtk_block_updates_stale_block() { +/Users/andrew/Programming/rtk/src/init.rs:1254: fn test_upsert_rtk_block_noop_when_already_current() { +/Users/andrew/Programming/rtk/src/init.rs:1262: fn test_upsert_rtk_block_detects_malformed_block() { +/Users/andrew/Programming/rtk/src/init.rs:1270: fn test_init_is_idempotent() { +/Users/andrew/Programming/rtk/src/init.rs:1282: fn test_local_init_unchanged() { +/Users/andrew/Programming/rtk/src/init.rs:1295: fn test_hook_already_present_exact_match() { +/Users/andrew/Programming/rtk/src/init.rs:1313: fn test_hook_already_present_different_path() { +/Users/andrew/Programming/rtk/src/init.rs:1332: fn test_hook_not_present_empty() { +/Users/andrew/Programming/rtk/src/init.rs:1339: fn test_hook_not_present_other_hooks() { +/Users/andrew/Programming/rtk/src/init.rs:1358: fn test_insert_hook_entry_empty_root() { +/Users/andrew/Programming/rtk/src/init.rs:1380: fn test_insert_hook_entry_preserves_existing() { +/Users/andrew/Programming/rtk/src/init.rs:1409: fn test_insert_hook_preserves_other_keys() { +/Users/andrew/Programming/rtk/src/init.rs:1430: fn test_atomic_write() { +/Users/andrew/Programming/rtk/src/init.rs:1444: fn test_preserve_order_round_trip() { +/Users/andrew/Programming/rtk/src/init.rs:1462: fn test_clean_double_blanks() { +/Users/andrew/Programming/rtk/src/init.rs:1474: fn test_clean_double_blanks_preserves_single() { +/Users/andrew/Programming/rtk/src/init.rs:1481: fn test_remove_hook_from_json() { +/Users/andrew/Programming/rtk/src/init.rs:1516: fn test_remove_hook_when_not_present() { +/Users/andrew/Programming/rtk/src/diff_cmd.rs:8:pub fn run(file1: &Path, file2: &Path, verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/diff_cmd.rs:69:pub fn run_stdin(_verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/diff_cmd.rs:99:fn compute_diff(lines1: &[&str], lines2: &[&str]) -> DiffResult { +/Users/andrew/Programming/rtk/src/diff_cmd.rs:145:fn similarity(a: &str, b: &str) -> f64 { +/Users/andrew/Programming/rtk/src/diff_cmd.rs:159:fn condense_unified_diff(diff: &str) -> String { +/Users/andrew/Programming/rtk/src/diff_cmd.rs:221: fn test_similarity_identical() { +/Users/andrew/Programming/rtk/src/diff_cmd.rs:226: fn test_similarity_completely_different() { +/Users/andrew/Programming/rtk/src/diff_cmd.rs:231: fn test_similarity_empty_strings() { +/Users/andrew/Programming/rtk/src/diff_cmd.rs:237: fn test_similarity_partial_overlap() { +/Users/andrew/Programming/rtk/src/diff_cmd.rs:244: fn test_similarity_threshold_for_modified() { +/Users/andrew/Programming/rtk/src/diff_cmd.rs:252: fn test_truncate_short_string() { +/Users/andrew/Programming/rtk/src/diff_cmd.rs:257: fn test_truncate_exact_length() { +/Users/andrew/Programming/rtk/src/diff_cmd.rs:262: fn test_truncate_long_string() { +/Users/andrew/Programming/rtk/src/diff_cmd.rs:269: fn test_compute_diff_identical() { +/Users/andrew/Programming/rtk/src/diff_cmd.rs:280: fn test_compute_diff_added_lines() { +/Users/andrew/Programming/rtk/src/diff_cmd.rs:289: fn test_compute_diff_removed_lines() { +/Users/andrew/Programming/rtk/src/diff_cmd.rs:298: fn test_compute_diff_modified_line() { +/Users/andrew/Programming/rtk/src/diff_cmd.rs:309: fn test_compute_diff_completely_different_line() { +/Users/andrew/Programming/rtk/src/diff_cmd.rs:320: fn test_compute_diff_empty_inputs() { +/Users/andrew/Programming/rtk/src/diff_cmd.rs:330: fn test_condense_unified_diff_single_file() { +/Users/andrew/Programming/rtk/src/diff_cmd.rs:335: fn main() { +/Users/andrew/Programming/rtk/src/diff_cmd.rs:347: fn test_condense_unified_diff_multiple_files() { +/Users/andrew/Programming/rtk/src/diff_cmd.rs:363: fn test_condense_unified_diff_empty() { +/Users/andrew/Programming/rtk/src/filter.rs:15: fn from_str(s: &str) -> Result { +/Users/andrew/Programming/rtk/src/filter.rs:26: fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +/Users/andrew/Programming/rtk/src/filter.rs:36: fn filter(&self, content: &str, lang: &Language) -> String; +/Users/andrew/Programming/rtk/src/filter.rs:38: fn name(&self) -> &'static str; +/Users/andrew/Programming/rtk/src/filter.rs:57: pub fn from_extension(ext: &str) -> Self { +/Users/andrew/Programming/rtk/src/filter.rs:73: pub fn comment_patterns(&self) -> CommentPatterns { +/Users/andrew/Programming/rtk/src/filter.rs:138: fn filter(&self, content: &str, _lang: &Language) -> String { +/Users/andrew/Programming/rtk/src/filter.rs:142: fn name(&self) -> &'static str { +/Users/andrew/Programming/rtk/src/filter.rs:155: fn filter(&self, content: &str, lang: &Language) -> String { +/Users/andrew/Programming/rtk/src/filter.rs:223: fn name(&self) -> &'static str { +/Users/andrew/Programming/rtk/src/filter.rs:234: r"^(pub\s+)?(async\s+)?(fn|def|function|func|class|struct|enum|trait|interface|type)\s+\w+" +/Users/andrew/Programming/rtk/src/filter.rs:240: fn filter(&self, content: &str, lang: &Language) -> String { +/Users/andrew/Programming/rtk/src/filter.rs:304: fn name(&self) -> &'static str { +/Users/andrew/Programming/rtk/src/filter.rs:309:pub fn get_filter(level: FilterLevel) -> Box { +/Users/andrew/Programming/rtk/src/filter.rs:317:pub fn smart_truncate(content: &str, max_lines: usize, _lang: &Language) -> String { +/Users/andrew/Programming/rtk/src/filter.rs:373: fn test_filter_level_parsing() { +/Users/andrew/Programming/rtk/src/filter.rs:386: fn test_language_detection() { +/Users/andrew/Programming/rtk/src/filter.rs:393: fn test_minimal_filter_removes_comments() { +/Users/andrew/Programming/rtk/src/filter.rs:396:fn main() { +/Users/andrew/Programming/rtk/src/filter.rs:403: assert!(result.contains("fn main()")); +/Users/andrew/Programming/rtk/src/display_helpers.rs:10:pub fn format_duration(ms: u64) -> String { +/Users/andrew/Programming/rtk/src/display_helpers.rs:25: fn icon() -> &'static str; +/Users/andrew/Programming/rtk/src/display_helpers.rs:28: fn label() -> &'static str; +/Users/andrew/Programming/rtk/src/display_helpers.rs:31: fn period(&self) -> String; +/Users/andrew/Programming/rtk/src/display_helpers.rs:34: fn commands(&self) -> usize; +/Users/andrew/Programming/rtk/src/display_helpers.rs:37: fn input_tokens(&self) -> usize; +/Users/andrew/Programming/rtk/src/display_helpers.rs:40: fn output_tokens(&self) -> usize; +/Users/andrew/Programming/rtk/src/display_helpers.rs:43: fn saved_tokens(&self) -> usize; +/Users/andrew/Programming/rtk/src/display_helpers.rs:46: fn savings_pct(&self) -> f64; +/Users/andrew/Programming/rtk/src/display_helpers.rs:49: fn total_time_ms(&self) -> u64; +/Users/andrew/Programming/rtk/src/display_helpers.rs:52: fn avg_time_ms(&self) -> u64; +/Users/andrew/Programming/rtk/src/display_helpers.rs:55: fn period_width() -> usize; +/Users/andrew/Programming/rtk/src/display_helpers.rs:58: fn separator_width() -> usize; +/Users/andrew/Programming/rtk/src/display_helpers.rs:62:pub fn print_period_table(data: &[T]) { +/Users/andrew/Programming/rtk/src/display_helpers.rs:145: fn icon() -> &'static str { +/Users/andrew/Programming/rtk/src/display_helpers.rs:149: fn label() -> &'static str { +/Users/andrew/Programming/rtk/src/display_helpers.rs:153: fn period(&self) -> String { +/Users/andrew/Programming/rtk/src/display_helpers.rs:157: fn commands(&self) -> usize { +/Users/andrew/Programming/rtk/src/display_helpers.rs:161: fn input_tokens(&self) -> usize { +/Users/andrew/Programming/rtk/src/display_helpers.rs:165: fn output_tokens(&self) -> usize { +/Users/andrew/Programming/rtk/src/display_helpers.rs:169: fn saved_tokens(&self) -> usize { +/Users/andrew/Programming/rtk/src/display_helpers.rs:173: fn savings_pct(&self) -> f64 { +/Users/andrew/Programming/rtk/src/display_helpers.rs:177: fn total_time_ms(&self) -> u64 { +/Users/andrew/Programming/rtk/src/display_helpers.rs:181: fn avg_time_ms(&self) -> u64 { +/Users/andrew/Programming/rtk/src/display_helpers.rs:185: fn period_width() -> usize { +/Users/andrew/Programming/rtk/src/display_helpers.rs:189: fn separator_width() -> usize { +/Users/andrew/Programming/rtk/src/display_helpers.rs:195: fn icon() -> &'static str { +/Users/andrew/Programming/rtk/src/display_helpers.rs:199: fn label() -> &'static str { +/Users/andrew/Programming/rtk/src/display_helpers.rs:203: fn period(&self) -> String { +/Users/andrew/Programming/rtk/src/display_helpers.rs:217: fn commands(&self) -> usize { +/Users/andrew/Programming/rtk/src/display_helpers.rs:221: fn input_tokens(&self) -> usize { +/Users/andrew/Programming/rtk/src/display_helpers.rs:225: fn output_tokens(&self) -> usize { +/Users/andrew/Programming/rtk/src/display_helpers.rs:229: fn saved_tokens(&self) -> usize { +/Users/andrew/Programming/rtk/src/display_helpers.rs:233: fn savings_pct(&self) -> f64 { +/Users/andrew/Programming/rtk/src/display_helpers.rs:237: fn total_time_ms(&self) -> u64 { +/Users/andrew/Programming/rtk/src/display_helpers.rs:241: fn avg_time_ms(&self) -> u64 { +/Users/andrew/Programming/rtk/src/display_helpers.rs:245: fn period_width() -> usize { +/Users/andrew/Programming/rtk/src/display_helpers.rs:249: fn separator_width() -> usize { +/Users/andrew/Programming/rtk/src/display_helpers.rs:255: fn icon() -> &'static str { +/Users/andrew/Programming/rtk/src/display_helpers.rs:259: fn label() -> &'static str { +/Users/andrew/Programming/rtk/src/display_helpers.rs:263: fn period(&self) -> String { +/Users/andrew/Programming/rtk/src/display_helpers.rs:267: fn commands(&self) -> usize { +/Users/andrew/Programming/rtk/src/display_helpers.rs:271: fn input_tokens(&self) -> usize { +/Users/andrew/Programming/rtk/src/display_helpers.rs:275: fn output_tokens(&self) -> usize { +/Users/andrew/Programming/rtk/src/display_helpers.rs:279: fn saved_tokens(&self) -> usize { +/Users/andrew/Programming/rtk/src/display_helpers.rs:283: fn savings_pct(&self) -> f64 { +/Users/andrew/Programming/rtk/src/display_helpers.rs:287: fn total_time_ms(&self) -> u64 { +/Users/andrew/Programming/rtk/src/display_helpers.rs:291: fn avg_time_ms(&self) -> u64 { +/Users/andrew/Programming/rtk/src/display_helpers.rs:295: fn period_width() -> usize { +/Users/andrew/Programming/rtk/src/display_helpers.rs:299: fn separator_width() -> usize { +/Users/andrew/Programming/rtk/src/display_helpers.rs:309: fn test_day_stats_trait() { +/Users/andrew/Programming/rtk/src/display_helpers.rs:330: fn test_week_stats_trait() { +/Users/andrew/Programming/rtk/src/display_helpers.rs:350: fn test_month_stats_trait() { +/Users/andrew/Programming/rtk/src/display_helpers.rs:369: fn test_print_period_table_empty() { +/Users/andrew/Programming/rtk/src/display_helpers.rs:376: fn test_print_period_table_with_data() { +/Users/andrew/Programming/rtk/src/prettier_cmd.rs:5:pub fn run(args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/prettier_cmd.rs:47:fn filter_prettier_output(output: &str) -> String { +/Users/andrew/Programming/rtk/src/prettier_cmd.rs:146: fn test_filter_all_formatted() { +/Users/andrew/Programming/rtk/src/prettier_cmd.rs:157: fn test_filter_files_need_formatting() { +/Users/andrew/Programming/rtk/src/prettier_cmd.rs:172: fn test_filter_many_files() { +/Users/andrew/Programming/rtk/src/next_cmd.rs:7:pub fn run(args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/next_cmd.rs:58:fn filter_next_build(output: &str) -> String { +/Users/andrew/Programming/rtk/src/next_cmd.rs:188:fn extract_time(line: &str) -> Option { +/Users/andrew/Programming/rtk/src/next_cmd.rs:203: fn test_filter_next_build() { +/Users/andrew/Programming/rtk/src/next_cmd.rs:233: fn test_extract_time() { +/Users/andrew/Programming/rtk/src/env_cmd.rs:7:pub fn run(filter: Option<&str>, show_all: bool, verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/env_cmd.rs:130:fn get_sensitive_patterns() -> HashSet<&'static str> { +/Users/andrew/Programming/rtk/src/env_cmd.rs:146:fn mask_value(value: &str) -> String { +/Users/andrew/Programming/rtk/src/env_cmd.rs:157:fn is_lang_var(key: &str) -> bool { +/Users/andrew/Programming/rtk/src/env_cmd.rs:165:fn is_cloud_var(key: &str) -> bool { +/Users/andrew/Programming/rtk/src/env_cmd.rs:183:fn is_tool_var(key: &str) -> bool { +/Users/andrew/Programming/rtk/src/env_cmd.rs:201:fn is_interesting_var(key: &str) -> bool { +/Users/andrew/Programming/rtk/src/container.rs:16:pub fn run(cmd: ContainerCmd, args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/container.rs:27:fn docker_ps(_verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/container.rs:84:fn docker_images(_verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/container.rs:154:fn docker_logs(args: &[String], _verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/container.rs:184:fn kubectl_pods(args: &[String], _verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/container.rs:285:fn kubectl_services(args: &[String], _verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/container.rs:359:fn kubectl_logs(args: &[String], _verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/container.rs:388:fn compact_ports(ports: &str) -> String { +/Users/andrew/Programming/rtk/src/container.rs:411:pub fn run_docker_passthrough(args: &[OsString], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/container.rs:435:pub fn run_kubectl_passthrough(args: &[OsString], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/utils.rs:24:pub fn truncate(s: &str, max_len: usize) -> String { +/Users/andrew/Programming/rtk/src/utils.rs:47:pub fn strip_ansi(text: &str) -> String { +/Users/andrew/Programming/rtk/src/utils.rs:70:pub fn execute_command(cmd: &str, args: &[&str]) -> Result<(String, String, i32)> { +/Users/andrew/Programming/rtk/src/utils.rs:98:pub fn format_tokens(n: usize) -> String { +/Users/andrew/Programming/rtk/src/utils.rs:124:pub fn format_usd(amount: f64) -> String { +/Users/andrew/Programming/rtk/src/utils.rs:150:pub fn format_cpt(cpt: f64) -> String { +/Users/andrew/Programming/rtk/src/utils.rs:167:pub fn ok_confirmation(action: &str, detail: &str) -> String { +/Users/andrew/Programming/rtk/src/utils.rs:185:pub fn detect_package_manager() -> &'static str { +/Users/andrew/Programming/rtk/src/utils.rs:197:pub fn package_manager_exec(tool: &str) -> Command { +/Users/andrew/Programming/rtk/src/utils.rs:233: fn test_truncate_short_string() { +/Users/andrew/Programming/rtk/src/utils.rs:238: fn test_truncate_long_string() { +/Users/andrew/Programming/rtk/src/utils.rs:244: fn test_truncate_exact_length() { +/Users/andrew/Programming/rtk/src/utils.rs:249: fn test_truncate_edge_case() { +/Users/andrew/Programming/rtk/src/utils.rs:259: fn test_strip_ansi_simple() { +/Users/andrew/Programming/rtk/src/utils.rs:265: fn test_strip_ansi_multiple() { +/Users/andrew/Programming/rtk/src/utils.rs:271: fn test_strip_ansi_no_codes() { +/Users/andrew/Programming/rtk/src/utils.rs:276: fn test_strip_ansi_complex() { +/Users/andrew/Programming/rtk/src/utils.rs:282: fn test_execute_command_success() { +/Users/andrew/Programming/rtk/src/utils.rs:291: fn test_execute_command_failure() { +/Users/andrew/Programming/rtk/src/utils.rs:297: fn test_format_tokens_millions() { +/Users/andrew/Programming/rtk/src/utils.rs:303: fn test_format_tokens_thousands() { +/Users/andrew/Programming/rtk/src/utils.rs:309: fn test_format_tokens_small() { +/Users/andrew/Programming/rtk/src/utils.rs:315: fn test_format_usd_large() { +/Users/andrew/Programming/rtk/src/utils.rs:321: fn test_format_usd_medium() { +/Users/andrew/Programming/rtk/src/utils.rs:327: fn test_format_usd_small() { +/Users/andrew/Programming/rtk/src/utils.rs:333: fn test_format_usd_edge() { +/Users/andrew/Programming/rtk/src/utils.rs:339: fn test_ok_confirmation_with_detail() { +/Users/andrew/Programming/rtk/src/utils.rs:348: fn test_ok_confirmation_no_detail() { +/Users/andrew/Programming/rtk/src/utils.rs:353: fn test_format_cpt_normal() { +/Users/andrew/Programming/rtk/src/utils.rs:360: fn test_format_cpt_edge_cases() { +/Users/andrew/Programming/rtk/src/utils.rs:368: fn test_detect_package_manager_default() { +/Users/andrew/Programming/rtk/src/utils.rs:376: fn test_truncate_multibyte_thai() { +/Users/andrew/Programming/rtk/src/utils.rs:386: fn test_truncate_multibyte_emoji() { +/Users/andrew/Programming/rtk/src/utils.rs:393: fn test_truncate_multibyte_cjk() { +/Users/andrew/Programming/rtk/src/gh_cmd.rs:15:pub fn run(subcommand: &str, args: &[String], verbose: u8, ultra_compact: bool) -> Result<()> { +/Users/andrew/Programming/rtk/src/gh_cmd.rs:29:fn run_pr(args: &[String], verbose: u8, ultra_compact: bool) -> Result<()> { +/Users/andrew/Programming/rtk/src/gh_cmd.rs:48:fn list_prs(args: &[String], _verbose: u8, ultra_compact: bool) -> Result<()> { +/Users/andrew/Programming/rtk/src/gh_cmd.rs:132:fn view_pr(args: &[String], _verbose: u8, ultra_compact: bool) -> Result<()> { +/Users/andrew/Programming/rtk/src/gh_cmd.rs:305:fn pr_checks(args: &[String], _verbose: u8, _ultra_compact: bool) -> Result<()> { +/Users/andrew/Programming/rtk/src/gh_cmd.rs:391:fn pr_status(_verbose: u8, _ultra_compact: bool) -> Result<()> { +/Users/andrew/Programming/rtk/src/gh_cmd.rs:435:fn run_issue(args: &[String], verbose: u8, ultra_compact: bool) -> Result<()> { +/Users/andrew/Programming/rtk/src/gh_cmd.rs:447:fn list_issues(args: &[String], _verbose: u8, ultra_compact: bool) -> Result<()> { +/Users/andrew/Programming/rtk/src/gh_cmd.rs:514:fn view_issue(args: &[String], _verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/gh_cmd.rs:600:fn run_workflow(args: &[String], verbose: u8, ultra_compact: bool) -> Result<()> { +/Users/andrew/Programming/rtk/src/gh_cmd.rs:612:fn list_runs(args: &[String], _verbose: u8, ultra_compact: bool) -> Result<()> { +/Users/andrew/Programming/rtk/src/gh_cmd.rs:695:fn view_run(args: &[String], _verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/gh_cmd.rs:763:fn run_repo(args: &[String], _verbose: u8, _ultra_compact: bool) -> Result<()> { +/Users/andrew/Programming/rtk/src/gh_cmd.rs:844:fn pr_create(args: &[String], _verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/gh_cmd.rs:882:fn pr_merge(args: &[String], _verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/gh_cmd.rs:928:fn pr_diff(args: &[String], _verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/gh_cmd.rs:962:fn pr_action(action: &str, args: &[String], _verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/gh_cmd.rs:1014:fn run_api(args: &[String], _verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/gh_cmd.rs:1058:fn run_passthrough(cmd: &str, subcommand: &str, args: &[String]) -> Result<()> { +/Users/andrew/Programming/rtk/src/gh_cmd.rs:1089: fn test_truncate() { +/Users/andrew/Programming/rtk/src/gh_cmd.rs:1098: fn test_truncate_multibyte_utf8() { +/Users/andrew/Programming/rtk/src/gh_cmd.rs:1108: fn test_truncate_empty_and_short() { +/Users/andrew/Programming/rtk/src/gh_cmd.rs:1115: fn test_ok_confirmation_pr_create() { +/Users/andrew/Programming/rtk/src/gh_cmd.rs:1122: fn test_ok_confirmation_pr_merge() { +/Users/andrew/Programming/rtk/src/gh_cmd.rs:1128: fn test_ok_confirmation_pr_comment() { +/Users/andrew/Programming/rtk/src/gh_cmd.rs:1134: fn test_ok_confirmation_pr_edit() { +/Users/andrew/Programming/rtk/src/playwright_cmd.rs:72: fn parse(input: &str) -> ParseResult { +/Users/andrew/Programming/rtk/src/playwright_cmd.rs:108:fn collect_test_results( +/Users/andrew/Programming/rtk/src/playwright_cmd.rs:140:fn extract_playwright_regex(output: &str) -> Option { +/Users/andrew/Programming/rtk/src/playwright_cmd.rs:196:fn extract_failures_regex(output: &str) -> Vec { +/Users/andrew/Programming/rtk/src/playwright_cmd.rs:219:pub fn run(args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/playwright_cmd.rs:288: fn test_playwright_parser_json() { +/Users/andrew/Programming/rtk/src/playwright_cmd.rs:322: fn test_playwright_parser_regex_fallback() { +/Users/andrew/Programming/rtk/src/playwright_cmd.rs:334: fn test_playwright_parser_passthrough() { +/Users/andrew/Programming/rtk/src/summary.rs:8:pub fn run(command: &str, verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/summary.rs:40:fn summarize_output(output: &str, command: &str, success: bool) -> String { +/Users/andrew/Programming/rtk/src/summary.rs:79:fn detect_output_type(output: &str, command: &str) -> OutputType { +/Users/andrew/Programming/rtk/src/summary.rs:110:fn summarize_tests(output: &str, result: &mut Vec) { +/Users/andrew/Programming/rtk/src/summary.rs:161:fn summarize_build(output: &str, result: &mut Vec) { +/Users/andrew/Programming/rtk/src/summary.rs:207:fn summarize_logs_quick(output: &str, result: &mut Vec) { +/Users/andrew/Programming/rtk/src/summary.rs:230:fn summarize_list(output: &str, result: &mut Vec) { +/Users/andrew/Programming/rtk/src/summary.rs:242:fn summarize_json(output: &str, result: &mut Vec) { +/Users/andrew/Programming/rtk/src/summary.rs:269:fn summarize_generic(output: &str, result: &mut Vec) { +/Users/andrew/Programming/rtk/src/summary.rs:292:fn extract_number(text: &str, after: &str) -> Option { diff --git a/benchmarks/quality_samples/E2_head_n.txt b/benchmarks/quality_samples/E2_head_n.txt new file mode 100644 index 0000000..cdadeca --- /dev/null +++ b/benchmarks/quality_samples/E2_head_n.txt @@ -0,0 +1,100 @@ +/Users/andrew/Programming/rtk/src/pip_cmd.rs:14:pub fn run(args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/pip_cmd.rs:53:fn run_list(base_cmd: &str, args: &[String], verbose: u8) -> Result<(String, String)> { +/Users/andrew/Programming/rtk/src/pip_cmd.rs:88:fn run_outdated(base_cmd: &str, args: &[String], verbose: u8) -> Result<(String, String)> { +/Users/andrew/Programming/rtk/src/pip_cmd.rs:123:fn run_passthrough(base_cmd: &str, args: &[String], verbose: u8) -> Result<(String, String)> { +/Users/andrew/Programming/rtk/src/pip_cmd.rs:157:fn which_command(cmd: &str) -> Option { +/Users/andrew/Programming/rtk/src/pip_cmd.rs:169:fn filter_pip_list(output: &str) -> String { +/Users/andrew/Programming/rtk/src/pip_cmd.rs:214:fn filter_pip_outdated(output: &str) -> String { +/Users/andrew/Programming/rtk/src/pip_cmd.rs:259: fn test_filter_pip_list() { +/Users/andrew/Programming/rtk/src/pip_cmd.rs:274: fn test_filter_pip_list_empty() { +/Users/andrew/Programming/rtk/src/pip_cmd.rs:281: fn test_filter_pip_outdated_none() { +/Users/andrew/Programming/rtk/src/pip_cmd.rs:289: fn test_filter_pip_outdated_some() { +/Users/andrew/Programming/rtk/src/pytest_cmd.rs:14:pub fn run(args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/pytest_cmd.rs:79:fn which_command(cmd: &str) -> Option { +/Users/andrew/Programming/rtk/src/pytest_cmd.rs:91:fn filter_pytest_output(output: &str) -> String { +/Users/andrew/Programming/rtk/src/pytest_cmd.rs:170:fn build_pytest_summary(summary: &str, _test_files: &[String], failures: &[String]) -> String { +/Users/andrew/Programming/rtk/src/pytest_cmd.rs:249:fn parse_summary_line(summary: &str) -> (usize, usize, usize) { +/Users/andrew/Programming/rtk/src/pytest_cmd.rs:286: fn test_filter_pytest_all_pass() { +/Users/andrew/Programming/rtk/src/pytest_cmd.rs:301: fn test_filter_pytest_with_failures() { +/Users/andrew/Programming/rtk/src/pytest_cmd.rs:327: fn test_filter_pytest_multiple_failures() { +/Users/andrew/Programming/rtk/src/pytest_cmd.rs:354: fn test_filter_pytest_no_tests() { +/Users/andrew/Programming/rtk/src/pytest_cmd.rs:365: fn test_parse_summary_line() { +/Users/andrew/Programming/rtk/src/ls.rs:33:pub fn run(args: &[String], verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/ls.rs:124:fn human_size(bytes: u64) -> String { +/Users/andrew/Programming/rtk/src/ls.rs:137:fn compact_ls(raw: &str, show_all: bool) -> String { +/Users/andrew/Programming/rtk/src/ls.rs:233: fn test_compact_basic() { +/Users/andrew/Programming/rtk/src/ls.rs:254: fn test_compact_filters_noise() { +/Users/andrew/Programming/rtk/src/ls.rs:270: fn test_compact_show_all() { +/Users/andrew/Programming/rtk/src/ls.rs:280: fn test_compact_empty() { +/Users/andrew/Programming/rtk/src/ls.rs:287: fn test_compact_summary() { +/Users/andrew/Programming/rtk/src/ls.rs:300: fn test_human_size() { +/Users/andrew/Programming/rtk/src/ls.rs:310: fn test_compact_handles_filenames_with_spaces() { +/Users/andrew/Programming/rtk/src/ls.rs:318: fn test_compact_symlinks() { +/Users/andrew/Programming/rtk/src/local_llm.rs:9:pub fn run(file: &Path, _model: &str, _force_download: bool, verbose: u8) -> Result<()> { +/Users/andrew/Programming/rtk/src/local_llm.rs:36:fn analyze_code(content: &str, lang: &Language) -> CodeSummary { +/Users/andrew/Programming/rtk/src/local_llm.rs:62: (!functions.is_empty()).then(|| format!("{} fn", functions.len())), +/Users/andrew/Programming/rtk/src/local_llm.rs:97: let key_fns: Vec<&str> = functions.iter().take(3).map(|s| s.as_str()).collect(); +/Users/andrew/Programming/rtk/src/local_llm.rs:99: details.push(format!("defines: {}", key_fns.join(", "))); +/Users/andrew/Programming/rtk/src/local_llm.rs:112:fn lang_display_name(lang: &Language) -> &'static str { +/Users/andrew/Programming/rtk/src/local_llm.rs:128:fn extract_imports(content: &str, lang: &Language) -> Vec { +/Users/andrew/Programming/rtk/src/local_llm.rs:159:fn is_std_import(name: &str, lang: &Language) -> bool { +/Users/andrew/Programming/rtk/src/local_llm.rs:167:fn extract_functions(content: &str, lang: &Language) -> Vec { +/Users/andrew/Programming/rtk/src/local_llm.rs:169: Language::Rust => r"(?:pub\s+)?(?:async\s+)?fn\s+([a-zA-Z_][a-zA-Z0-9_]*)", +/Users/andrew/Programming/rtk/src/local_llm.rs:195:fn extract_structs(content: &str, lang: &Language) -> Vec { +/Users/andrew/Programming/rtk/src/local_llm.rs:212:fn extract_traits(content: &str, lang: &Language) -> Vec { +/Users/andrew/Programming/rtk/src/local_llm.rs:226:fn detect_patterns(content: &str, lang: &Language) -> Vec { +/Users/andrew/Programming/rtk/src/local_llm.rs:279: fn test_rust_analysis() { +/Users/andrew/Programming/rtk/src/local_llm.rs:288:pub fn load_config() -> Result { +/Users/andrew/Programming/rtk/src/local_llm.rs:292:fn helper() {} +/Users/andrew/Programming/rtk/src/local_llm.rs:296: assert!(summary.line1.contains("fn")); +/Users/andrew/Programming/rtk/src/local_llm.rs:300: fn test_python_analysis() { +/Users/andrew/Programming/rtk/src/learn/detector.rs:16: pub fn as_str(&self) -> &str { +/Users/andrew/Programming/rtk/src/learn/detector.rs:76:pub fn is_command_error(is_error: bool, output: &str) -> bool { +/Users/andrew/Programming/rtk/src/learn/detector.rs:97:pub fn classify_error(output: &str) -> ErrorType { +/Users/andrew/Programming/rtk/src/learn/detector.rs:124:pub fn extract_base_command(cmd: &str) -> String { +/Users/andrew/Programming/rtk/src/learn/detector.rs:145:pub fn command_similarity(a: &str, b: &str) -> f64 { +/Users/andrew/Programming/rtk/src/learn/detector.rs:182:fn is_tdd_cycle_error(error_type: &ErrorType, output: &str) -> bool { +/Users/andrew/Programming/rtk/src/learn/detector.rs:199:fn differs_only_by_path(a: &str, b: &str) -> bool { +/Users/andrew/Programming/rtk/src/learn/detector.rs:213:pub fn find_corrections(commands: &[CommandExecution]) -> Vec { +/Users/andrew/Programming/rtk/src/learn/detector.rs:283:fn extract_diff_token(wrong: &str, right: &str) -> String { +/Users/andrew/Programming/rtk/src/learn/detector.rs:305:pub fn deduplicate_corrections(pairs: Vec) -> Vec { +/Users/andrew/Programming/rtk/src/learn/detector.rs:357: fn test_is_command_error_requires_error_flag() { +/Users/andrew/Programming/rtk/src/learn/detector.rs:363: fn test_is_command_error_filters_user_rejection() { +/Users/andrew/Programming/rtk/src/learn/detector.rs:370: fn test_is_command_error_requires_error_content() { +/Users/andrew/Programming/rtk/src/learn/detector.rs:378: fn test_classify_error_unknown_flag() { +/Users/andrew/Programming/rtk/src/learn/detector.rs:394: fn test_classify_error_command_not_found() { +/Users/andrew/Programming/rtk/src/learn/detector.rs:406: fn test_classify_error_all_types() { +/Users/andrew/Programming/rtk/src/learn/detector.rs:426: fn test_extract_base_command() { +/Users/andrew/Programming/rtk/src/learn/detector.rs:440: fn test_command_similarity_same_base() { +/Users/andrew/Programming/rtk/src/learn/detector.rs:451: fn test_find_corrections_basic() { +/Users/andrew/Programming/rtk/src/learn/detector.rs:473: fn test_find_corrections_window_limit() { +/Users/andrew/Programming/rtk/src/learn/detector.rs:508: fn test_find_corrections_excludes_tdd_cycle() { +/Users/andrew/Programming/rtk/src/learn/detector.rs:527: fn test_find_corrections_path_exploration() { +/Users/andrew/Programming/rtk/src/learn/detector.rs:549: fn test_find_corrections_min_confidence() { +/Users/andrew/Programming/rtk/src/learn/detector.rs:571: fn test_deduplicate_corrections_merges_same() { +/Users/andrew/Programming/rtk/src/learn/detector.rs:605: fn test_deduplicate_corrections_keeps_distinct() { +/Users/andrew/Programming/rtk/src/learn/report.rs:7:pub fn format_console_report( +/Users/andrew/Programming/rtk/src/learn/report.rs:52:pub fn write_rules_file(rules: &[CorrectionRule], path: &str) -> Result<()> { +/Users/andrew/Programming/rtk/src/learn/report.rs:110:fn capitalize_first(s: &str) -> String { +/Users/andrew/Programming/rtk/src/learn/report.rs:124: fn test_format_console_report_empty() { +/Users/andrew/Programming/rtk/src/learn/report.rs:132: fn test_format_console_report_with_rules() { +/Users/andrew/Programming/rtk/src/learn/report.rs:162: fn test_write_rules_file_markdown() { +/Users/andrew/Programming/rtk/src/learn/mod.rs:9:pub fn run( +/Users/andrew/Programming/rtk/src/discover/registry.rs:29:pub fn category_avg_tokens(category: &str, subcmd: &str) -> usize { +/Users/andrew/Programming/rtk/src/discover/registry.rs:314:pub fn classify_command(cmd: &str) -> Classification { +/Users/andrew/Programming/rtk/src/discover/registry.rs:392:fn extract_base_command(cmd: &str) -> &str { +/Users/andrew/Programming/rtk/src/discover/registry.rs:423:pub fn split_command_chain(cmd: &str) -> Vec<&str> { +/Users/andrew/Programming/rtk/src/discover/registry.rs:511: fn test_classify_git_status() { +/Users/andrew/Programming/rtk/src/discover/registry.rs:524: fn test_classify_git_diff_cached() { +/Users/andrew/Programming/rtk/src/discover/registry.rs:537: fn test_classify_cargo_test_filter() { +/Users/andrew/Programming/rtk/src/discover/registry.rs:550: fn test_classify_npx_tsc() { +/Users/andrew/Programming/rtk/src/discover/registry.rs:563: fn test_classify_cat_file() { +/Users/andrew/Programming/rtk/src/discover/registry.rs:576: fn test_classify_grepai_search() { +/Users/andrew/Programming/rtk/src/discover/registry.rs:589: fn test_classify_plain_rgai() { +/Users/andrew/Programming/rtk/src/discover/registry.rs:602: fn test_classify_cd_ignored() { +/Users/andrew/Programming/rtk/src/discover/registry.rs:607: fn test_classify_rtk_already() { +/Users/andrew/Programming/rtk/src/discover/registry.rs:612: fn test_classify_echo_ignored() { +/Users/andrew/Programming/rtk/src/discover/registry.rs:620: fn test_classify_terraform_unsupported() { +/Users/andrew/Programming/rtk/src/discover/registry.rs:630: fn test_classify_env_prefix_stripped() { +/Users/andrew/Programming/rtk/src/discover/registry.rs:643: fn test_classify_sudo_stripped() { +/Users/andrew/Programming/rtk/src/discover/registry.rs:656: fn test_classify_cargo_check() { diff --git a/benchmarks/quality_samples/E2_rtk_grep.txt b/benchmarks/quality_samples/E2_rtk_grep.txt new file mode 100644 index 0000000..0b4a6529 --- /dev/null +++ b/benchmarks/quality_samples/E2_rtk_grep.txt @@ -0,0 +1,264 @@ +🔍 784 in 54F: + +📄 /Users/andrew/Programming/rtk/src/cargo_cmd.rs (41): + 18: pub fn run(cmd: CargoCommand, args: &[String], verbose: u8) -> Result<()> { + 29: fn run_cargo_filtered(subcommand: &str, args: &[String], verbose: u8, filter_... + 52: let filtered = filter_fn(&raw); + 69: fn run_build(args: &[String], verbose: u8) -> Result<()> { + 73: fn run_test(args: &[String], verbose: u8) -> Result<()> { + 77: fn run_clippy(args: &[String], verbose: u8) -> Result<()> { + 81: fn run_check(args: &[String], verbose: u8) -> Result<()> { + 85: fn run_install(args: &[String], verbose: u8) -> Result<()> { + 90: fn format_crate_info(name: &str, version: &str, fallback: &str) -> String { + 101: fn filter_cargo_install(output: &str) -> String { + +31 + +📄 /Users/andrew/Programming/rtk/src/cc_economics.rs (36): + 54: fn new(label: &str) -> Self { + 76: fn set_ccusage(&mut self, metrics: &ccusage::CcusageMetrics) { + 91: fn set_rtk_from_day(&mut self, stats: &DayStats) { + 97: fn set_rtk_from_week(&mut self, stats: &WeekStats) { + 103: fn set_rtk_from_month(&mut self, stats: &MonthStats) { + 115: fn compute_weighted_metrics(&mut self) { + 141: fn compute_dual_metrics(&mut self) { + 184: pub fn run( + 203: fn merge_daily(cc: Option>, rtk: Vec) -> Vec>, rtk: Vec) -> Vec bool { + 95: fn build_command() -> Option { + 118: pub fn is_available() -> bool { + 127: pub fn fetch(granularity: Granularity) -> Result>> { + 176: fn parse_json(json: &str, granularity: Granularity) -> Result... + 222: fn test_parse_monthly_valid() { + 247: fn test_parse_daily_valid() { + 270: fn test_parse_weekly_valid() { + 293: fn test_parse_malformed_json() { + 300: fn test_parse_missing_required_fields() { + +2 + +📄 /Users/andrew/Programming/rtk/src/config.rs (8): + 24: fn default() -> Self { + 41: fn default() -> Self { + 57: fn default() -> Self { + 73: pub fn load() -> Result { + 85: pub fn save(&self) -> Result<()> { + 97: pub fn create_default() -> Result { + 104: fn get_config_path() -> Result { + 109: pub fn show_config() -> Result<()> { + +📄 /Users/andrew/Programming/rtk/src/container.rs (10): + 16: pub fn run(cmd: ContainerCmd, args: &[String], verbose: u8) -> Result<()> { + 27: fn docker_ps(_verbose: u8) -> Result<()> { + 84: fn docker_images(_verbose: u8) -> Result<()> { + 154: fn docker_logs(args: &[String], _verbose: u8) -> Result<()> { + 184: fn kubectl_pods(args: &[String], _verbose: u8) -> Result<()> { + 285: fn kubectl_services(args: &[String], _verbose: u8) -> Result<()> { + 359: fn kubectl_logs(args: &[String], _verbose: u8) -> Result<()> { + 388: fn compact_ports(ports: &str) -> String { + 411: pub fn run_docker_passthrough(args: &[OsString], verbose: u8) -> Result<()> { + 435: pub fn run_kubectl_passthrough(args: &[OsString], verbose: u8) -> Result<()> { + +📄 /Users/andrew/Programming/rtk/src/curl_cmd.rs (6): + 7: pub fn run(args: &[String], verbose: u8) -> Result<()> { + 50: fn filter_curl_output(output: &str) -> String { + 88: fn test_filter_curl_json() { + 97: fn test_filter_curl_json_array() { + 104: fn test_filter_curl_non_json() { + 112: fn test_filter_curl_long_output() { + +📄 /Users/andrew/Programming/rtk/src/deps.rs (6): + 8: pub fn run(path: &Path, verbose: u8) -> Result<()> { + 74: fn summarize_cargo_str(path: &Path) -> Result { + 127: fn summarize_package_json_str(path: &Path) -> Result { + 163: fn summarize_requirements_str(path: &Path) -> Result { + 191: fn summarize_pyproject_str(path: &Path) -> Result { + 227: fn summarize_gomod_str(path: &Path) -> Result { + +📄 /Users/andrew/Programming/rtk/src/diff_cmd.rs (23): + 8: pub fn run(file1: &Path, file2: &Path, verbose: u8) -> Result<()> { + 69: pub fn run_stdin(_verbose: u8) -> Result<()> { + 99: fn compute_diff(lines1: &[&str], lines2: &[&str]) -> DiffResult { + 145: fn similarity(a: &str, b: &str) -> f64 { + 159: fn condense_unified_diff(diff: &str) -> String { + 221: fn test_similarity_identical() { + 226: fn test_similarity_completely_different() { + 231: fn test_similarity_empty_strings() { + 237: fn test_similarity_partial_overlap() { + 244: fn test_similarity_threshold_for_modified() { + +13 + +📄 /Users/andrew/Programming/rtk/src/discover/mod.rs (3): + 29: pub fn run( + 219: fn extract_subcmd(cmd: &str) -> &str { + 229: fn truncate_command(cmd: &str) -> String { + +📄 /.../discover/provider.rs (18): + 26: fn discover_sessions( + 31: fn extract_commands(&self, path: &Path) -> Result>; + 38: fn projects_dir() -> Result { + 52: pub fn encode_project_path(path: &str) -> String { + 58: fn discover_sessions( + 119: fn extract_commands(&self, path: &Path) -> Result> { + 242: fn make_jsonl(lines: &[&str]) -> tempfile::NamedTempFile { + 252: fn test_extract_assistant_bash() { + 270: fn test_extract_non_bash_ignored() { + 281: fn test_extract_non_message_ignored() { + +8 + +📄 /.../discover/registry.rs (30): + 29: pub fn category_avg_tokens(category: &str, subcmd: &str) -> usize { + 314: pub fn classify_command(cmd: &str) -> Classification { + 392: fn extract_base_command(cmd: &str) -> &str { + 423: pub fn split_command_chain(cmd: &str) -> Vec<&str> { + 511: fn test_classify_git_status() { + 524: fn test_classify_git_diff_cached() { + 537: fn test_classify_cargo_test_filter() { + 550: fn test_classify_npx_tsc() { + 563: fn test_classify_cat_file() { + 576: fn test_classify_grepai_search() { + +20 + +📄 /.../discover/report.rs (7): + 15: pub fn as_str(&self) -> &'static str { + 57: pub fn total_saveable_tokens(&self) -> usize { + 64: pub fn total_supported_count(&self) -> usize { + 70: pub fn format_text(report: &DiscoverReport, limit: usize, verbose: bool) -> Stri... + 159: pub fn format_json(report: &DiscoverReport) -> String { + 163: fn format_tokens(tokens: usize) -> String { + 173: fn truncate_str(s: &str, max: usize) -> String { + +📄 /.../src/display_helpers.rs (55): + 10: pub fn format_duration(ms: u64) -> String { + 25: fn icon() -> &'static str; + 28: fn label() -> &'static str; + 31: fn period(&self) -> String; + 34: fn commands(&self) -> usize; + 37: fn input_tokens(&self) -> usize; + 40: fn output_tokens(&self) -> usize; + 43: fn saved_tokens(&self) -> usize; + 46: fn savings_pct(&self) -> f64; + 49: fn total_time_ms(&self) -> u64; + +45 + +📄 /Users/andrew/Programming/rtk/src/env_cmd.rs (7): + 7: pub fn run(filter: Option<&str>, show_all: bool, verbose: u8) -> Result<()> { + 130: fn get_sensitive_patterns() -> HashSet<&'static str> { + 146: fn mask_value(value: &str) -> String { + 157: fn is_lang_var(key: &str) -> bool { + 165: fn is_cloud_var(key: &str) -> bool { + 183: fn is_tool_var(key: &str) -> bool { + 201: fn is_interesting_var(key: &str) -> bool { + +📄 /Users/andrew/Programming/rtk/src/filter.rs (20): + 15: fn from_str(s: &str) -> Result { + 26: fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + 36: fn filter(&self, content: &str, lang: &Language) -> String; + 38: fn name(&self) -> &'static str; + 57: pub fn from_extension(ext: &str) -> Self { + 73: pub fn comment_patterns(&self) -> CommentPatterns { + 138: fn filter(&self, content: &str, _lang: &Language) -> String { + 142: fn name(&self) -> &'static str { + 155: fn filter(&self, content: &str, lang: &Language) -> String { + 223: fn name(&self) -> &'static str { + +10 + +📄 /Users/andrew/Programming/rtk/src/find_cmd.rs (14): + 8: fn glob_match(pattern: &str, name: &str) -> bool { + 12: fn glob_match_inner(pat: &[u8], name: &[u8]) -> bool { + 26: pub fn run( + 212: fn glob_match_star_rs() { + 220: fn glob_match_star_all() { + 227: fn glob_match_question_mark() { + 233: fn glob_match_exact() { + 239: fn glob_match_complex() { + 248: fn dot_becomes_star() { + 257: fn find_rs_files_in_src() { + +4 + +📄 /Users/andrew/Programming/rtk/src/gain.rs (7): + 7: pub fn run( + 160: fn print_ascii_graph(data: &[(String, usize)]) { + 190: fn print_daily_full(tracker: &Tracker) -> Result<()> { + 196: fn print_weekly(tracker: &Tracker) -> Result<()> { + 202: fn print_monthly(tracker: &Tracker) -> Result<()> { + 230: fn export_json( + 274: fn export_csv( + +📄 /Users/andrew/Programming/rtk/src/gh_cmd.rs (26): + 15: pub fn run(subcommand: &str, args: &[String], verbose: u8, ultra_compact: bool) ... + 29: fn run_pr(args: &[String], verbose: u8, ultra_compact: bool) -> Result<()> { + 48: fn list_prs(args: &[String], _verbose: u8, ultra_compact: bool) -> Result<()> { + 132: fn view_pr(args: &[String], _verbose: u8, ultra_compact: bool) -> Result<()> { + 305: fn pr_checks(args: &[String], _verbose: u8, _ultra_compact: bool) -> Result<()> ... + 391: fn pr_status(_verbose: u8, _ultra_compact: bool) -> Result<()> { + 435: fn run_issue(args: &[String], verbose: u8, ultra_compact: bool) -> Result<()> { + 447: fn list_issues(args: &[String], _verbose: u8, ultra_compact: bool) -> Result<()>... + 514: fn view_issue(args: &[String], _verbose: u8) -> Result<()> { + 600: fn run_workflow(args: &[String], verbose: u8, ultra_compact: bool) -> Result<()>... + +16 + +📄 /Users/andrew/Programming/rtk/src/git.rs (42): + 22: pub fn run(cmd: GitCommand, args: &[String], max_lines: Option, verbose: ... + 39: fn run_diff(args: &[String], max_lines: Option, verbose: u8) -> Result<()... + 126: fn run_show(args: &[String], max_lines: Option, verbose: u8) -> Result<()... + 232: pub(crate) fn compact_diff(diff: &str, max_lines: usize) -> String { + 298: fn run_log(args: &[String], _max_lines: Option, verbose: u8) -> Result<()... + 375: fn filter_log_output(output: &str, limit: usize) -> String { + 394: fn format_status_output(porcelain: &str) -> String { + 490: fn filter_status_with_args(output: &str) -> String { + 526: fn run_status(args: &[String], verbose: u8) -> Result<()> { + 582: fn run_add(args: &[String], verbose: u8) -> Result<()> { + +32 + +📄 /Users/andrew/Programming/rtk/src/go_cmd.rs (15): + 34: pub fn run_test(args: &[String], verbose: u8) -> Result<()> { + 85: pub fn run_build(args: &[String], verbose: u8) -> Result<()> { + 128: pub fn run_vet(args: &[String], verbose: u8) -> Result<()> { + 171: pub fn run_other(args: &[OsString], verbose: u8) -> Result<()> { + 217: fn filter_go_test_json(output: &str) -> String { + 341: fn filter_go_build(output: &str) -> String { + 384: fn filter_go_vet(output: &str) -> String { + 416: fn compact_package_name(package: &str) -> String { + 430: fn test_filter_go_test_all_pass() { + 443: fn test_filter_go_test_with_failures() { + +5 + +📄 /Users/andrew/Programming/rtk/src/golangci_cmd.rs (6): + 34: pub fn run(args: &[String], verbose: u8) -> Result<()> { + 88: fn filter_golangci_json(output: &str) -> String { + 179: fn compact_path(path: &str) -> String { + 200: fn test_filter_golangci_no_issues() { + 208: fn test_filter_golangci_with_issues() { + 239: fn test_compact_path() { + +📄 /Users/andrew/Programming/rtk/src/grep_cmd.rs (8): + 7: pub fn run( + 120: fn clean_line(line: &str, max_len: usize, context_only: bool, pattern: &str) -> ... + 168: fn compact_path(path: &str) -> String { + 191: fn test_clean_line() { + 199: fn test_compact_path() { + 206: fn test_extra_args_accepted() { + 214: fn test_clean_line_multibyte() { + 223: fn test_clean_line_emoji() { + +📄 /Users/andrew/Programming/rtk/src/init.rs (52): + 176: pub fn run( + 192: fn prepare_hook_paths() -> Result<(PathBuf, PathBuf)> { + 203: fn ensure_hook_installed(hook_path: &Path, verbose: u8) -> Result { + 239: fn write_if_changed(path: &Path, content: &str, name: &str, verbose: u8) -> Resu... + 269: fn atomic_write(path: &Path, content: &str) -> Result<()> { + 300: fn prompt_user_consent(settings_path: &Path) -> Result { + 323: fn print_manual_instructions(hook_path: &Path) { + 338: fn remove_hook_from_json(root: &mut serde_json::Value) -> bool { + 369: fn remove_hook_from_settings(verbose: u8) -> Result { + 412: pub fn uninstall(global: bool, verbose: u8) -> Result<()> { + +42 + +📄 /Users/andrew/Programming/rtk/src/json_cmd.rs (6): + 9: pub fn run(file: &Path, max_depth: usize, verbose: u8) -> Result<()> { + 31: pub fn run_stdin(max_depth: usize, verbose: u8) -> Result<()> { + +... +584 diff --git a/benchmarks/quality_samples/E2_rtk_rgai.txt b/benchmarks/quality_samples/E2_rtk_rgai.txt new file mode 100644 index 0000000..abb21aa --- /dev/null +++ b/benchmarks/quality_samples/E2_rtk_rgai.txt @@ -0,0 +1,101 @@ +🧠 54F for 'fn' (scan 55F) + +📄 display_helpers.rs [9.7] + 9: /// Format duration in milliseconds to human-readable string + 10: pub fn format_duration(ms: u64) -> String { + 11: if ms < 1000 { + ~ fn + + 24: /// Icon for this period type (e.g., "📅", "📊", "📆") + 25: fn icon() -> &'static str; + ~ fn + + +53 more lines + +📄 init.rs [9.6] + 175: /// Main entry point for `rtk init` + 176: pub fn run( + 177: global: bool, + ~ fn + + 191: /// Prepare hook directory and return paths (hook_dir, hook_path) + 192: fn prepare_hook_paths() -> Result<(PathBuf, PathBuf)> { + 193: let claude_dir = resolve_claude_dir()?; + ~ fn + + +50 more lines + +📄 cargo_cmd.rs [9.4] + 18: pub fn run(cmd: CargoCommand, args: &[String], verbose: u8) -> Result<()> { + 19: match cmd { + ~ fn + + 28: /// Generic cargo command runner with filtering + 29: fn run_cargo_filtered(subcommand: &str, args: &[String], verbose: u8, filter_fn: F) -> Result<()> + 30: where + ~ fn + + +40 more lines + +📄 git.rs [9.4] + 22: pub fn run(cmd: GitCommand, args: &[String], max_lines: Option, verbose: u8) -> Result<()> { + 23: match cmd { + ~ fn + + 39: fn run_diff(args: &[String], max_lines: Option, verbose: u8) -> Result<()> { + 40: let timer = tracking::TimedExecution::start(); + ~ fn + + +40 more lines + +📄 cc_economics.rs [9.3] + 53: impl PeriodEconomics { + 54: fn new(label: &str) -> Self { + 55: Self { + ~ fn + + 76: fn set_ccusage(&mut self, metrics: &ccusage::CcusageMetrics) { + 77: self.cc_cost = Some(metrics.total_cost); + ~ fn + + +34 more lines + +📄 utils.rs [9.2] + 23: /// ``` + 24: pub fn truncate(s: &str, max_len: usize) -> String { + 25: let char_count = s.chars().count(); + ~ fn + + 46: /// ``` + 47: pub fn strip_ansi(text: &str) -> String { + 48: lazy_static::lazy_static! { + ~ fn + + +32 more lines + +📄 discover/registry.rs [9.1] + 28: /// Average token counts per category for estimation when no output_len available. + 29: pub fn category_avg_tokens(category: &str, subcmd: &str) -> usize { + 30: match category { + ~ fn + + 313: /// Classify a single (already-split) command. + 314: pub fn classify_command(cmd: &str) -> Classification { + 315: let trimmed = cmd.trim(); + ~ fn + + +28 more lines + +📄 gh_cmd.rs [9.0] + 14: /// Run a gh command with token-optimized output + 15: pub fn run(subcommand: &str, args: &[String], verbose: u8, ultra_compact: bool) -> Result<()> { + 16: match subcommand { + ~ fn + + 29: fn run_pr(args: &[String], verbose: u8, ultra_compact: bool) -> Result<()> { + 30: if args.is_empty() { + ~ fn + + +24 more lines + +... +46F diff --git a/benchmarks/quality_samples/E3_grep.txt b/benchmarks/quality_samples/E3_grep.txt new file mode 100644 index 0000000..e69de29 diff --git a/benchmarks/quality_samples/E3_head_n.txt b/benchmarks/quality_samples/E3_head_n.txt new file mode 100644 index 0000000..e69de29 diff --git a/benchmarks/quality_samples/E3_rtk_grep.txt b/benchmarks/quality_samples/E3_rtk_grep.txt new file mode 100644 index 0000000..8fc0e21 --- /dev/null +++ b/benchmarks/quality_samples/E3_rtk_grep.txt @@ -0,0 +1 @@ +🔍 0 for 'error handling retry backoff' diff --git a/benchmarks/quality_samples/E3_rtk_rgai.txt b/benchmarks/quality_samples/E3_rtk_rgai.txt new file mode 100644 index 0000000..a769fed --- /dev/null +++ b/benchmarks/quality_samples/E3_rtk_rgai.txt @@ -0,0 +1,102 @@ +🧠 30F for 'error handling retry backoff' (scan 55F) + +📄 learn/detector.rs [10.7] + 4: #[derive(Debug, Clone, PartialEq)] + 5: pub enum ErrorType { + 6: UnknownFlag, + ~ error + + 15: impl ErrorType { + 16: pub fn as_str(&self) -> &str { + ~ error + + +99 more lines + +📄 cargo_cmd.rs [10.5] + 715: #[test] + 716: fn test_filter_cargo_build_errors() { + 717: let output = r#" Compiling rtk v0.5.0 + ~ error + + 996: #[test] + 997: fn test_filter_cargo_install_error() { + 998: let output = r#" Installing rtk v0.11.0 + ~ error + + +83 more lines + +📄 tsc_cmd.rs [9.8] + 66: struct TsError { + 67: file: String, + ~ error + + 197: #[test] + 198: fn test_every_error_message_shown() { + 199: let output = "\ + ~ error + + +37 more lines + +📄 parser/error.rs [9.4] + 4: #[derive(Error, Debug)] + 5: pub enum ParseError { + 6: #[error("JSON parse failed at line {line}, column {col}: {msg}")] + ~ error + + 38: impl From for ParseError { + 39: fn from(err: serde_json::Error) -> Self { + ~ error + + +5 more lines + +📄 runner.rs [9.0] + 90: fn filter_errors(output: &str) -> String { + 91: lazy_static::lazy_static! { + ~ error + + 248: #[test] + 249: fn test_filter_errors() { + 250: let output = "info: compiling\nerror: something failed\n at line 10\ninfo: done"; + ~ error + + +16 more lines + +📄 discover/provider.rs [7.7] + 358: #[test] + 359: fn test_extract_is_error_flag() { + 360: let jsonl = make_jsonl(&[ + ~ error + + 18: /// Whether the tool_result indicated an error + 19: pub is_error: bool, + 20: /// Chronological sequence index within the session + ~ error + + +12 more lines + +📄 go_cmd.rs [7.7] + 464: #[test] + 465: fn test_filter_go_build_errors() { + 466: let output = r#"# example.com/foo + ~ error + + 321: && !line.starts_with("--- FAIL") + 322: && (lower.contains("error") + 323: || lower.contains("expected") + ~ error + + +12 more lines + +📄 wget_cmd.rs [7.2] + 209: fn parse_error(stderr: &str, stdout: &str) -> String { + 210: // Common wget error patterns + ~ error + + 43: } else { + 44: let error = parse_error(&stderr, &stdout); + 45: let msg = format!("⬇️ {} FAILED: {}", compact_url(url), error); + ~ error + + +6 more lines + +... +22F diff --git a/benchmarks/results_env.txt b/benchmarks/results_env.txt new file mode 100644 index 0000000..a17e8e4 --- /dev/null +++ b/benchmarks/results_env.txt @@ -0,0 +1,13 @@ +Date: Sat Feb 14 22:34:25 UTC 2026 +Commit: 4b0a413562c775757d5bc09a6ff966b4e532508c +rtk_bin: /Users/andrew/Programming/rtk/target/release/rtk +rtk: rtk 0.15.3 +grep: grep (BSD grep, GNU compatible) 2.6.0-FreeBSD +tiktoken_encoding: cl100k_base +rtk_grep_max: 200 +rgai_max: 8 +head_n_lines: 100 +OS: Darwin MacBook-Pro-Andy.local 25.2.0 Darwin Kernel Version 25.2.0: Tue Nov 18 21:09:56 PST 2025; root:xnu-12377.61.12~1/RELEASE_ARM64_T6041 arm64 +CPU: Apple M4 Pro +Rust files: 54 +Total LOC: 23240 diff --git a/benchmarks/results_raw.csv b/benchmarks/results_raw.csv new file mode 100644 index 0000000..10f2c40 --- /dev/null +++ b/benchmarks/results_raw.csv @@ -0,0 +1,601 @@ +test_id,category,query,tool,run,time_us,output_bytes,output_tokens,result_count,exit_code +A1,exact_identifier,"TimedExecution",grep,1,5000,10338,2927,104,0 +A1,exact_identifier,"TimedExecution",rtk_grep,1,44000,6527,1979,159,0 +A1,exact_identifier,"TimedExecution",rtk_rgai,1,13000,2797,841,94,0 +A1,exact_identifier,"TimedExecution",head_n,1,0,9933,2810,100,0 +A1,exact_identifier,"TimedExecution",grep,2,7000,10338,2927,104,0 +A1,exact_identifier,"TimedExecution",rtk_grep,2,23000,6527,1979,159,0 +A1,exact_identifier,"TimedExecution",rtk_rgai,2,11000,2797,841,94,0 +A1,exact_identifier,"TimedExecution",head_n,2,0,9933,2810,100,0 +A1,exact_identifier,"TimedExecution",grep,3,6000,10338,2927,104,0 +A1,exact_identifier,"TimedExecution",rtk_grep,3,25000,6527,1979,159,0 +A1,exact_identifier,"TimedExecution",rtk_rgai,3,11000,2797,841,94,0 +A1,exact_identifier,"TimedExecution",head_n,3,0,9933,2810,100,0 +A1,exact_identifier,"TimedExecution",grep,4,6000,10338,2927,104,0 +A1,exact_identifier,"TimedExecution",rtk_grep,4,22000,6527,1979,159,0 +A1,exact_identifier,"TimedExecution",rtk_rgai,4,11000,2797,841,94,0 +A1,exact_identifier,"TimedExecution",head_n,4,0,9933,2810,100,0 +A1,exact_identifier,"TimedExecution",grep,5,6000,10338,2927,104,0 +A1,exact_identifier,"TimedExecution",rtk_grep,5,25000,6527,1979,159,0 +A1,exact_identifier,"TimedExecution",rtk_rgai,5,11000,2797,841,94,0 +A1,exact_identifier,"TimedExecution",head_n,5,0,9933,2810,100,0 +A2,exact_identifier,"FilterLevel",grep,1,5000,2196,605,23,0 +A2,exact_identifier,"FilterLevel",rtk_grep,1,25000,902,288,25,0 +A2,exact_identifier,"FilterLevel",rtk_rgai,1,10000,691,223,32,0 +A2,exact_identifier,"FilterLevel",head_n,1,0,2196,605,23,0 +A2,exact_identifier,"FilterLevel",grep,2,5000,2196,605,23,0 +A2,exact_identifier,"FilterLevel",rtk_grep,2,25000,902,288,25,0 +A2,exact_identifier,"FilterLevel",rtk_rgai,2,11000,691,223,32,0 +A2,exact_identifier,"FilterLevel",head_n,2,0,2196,605,23,0 +A2,exact_identifier,"FilterLevel",grep,3,5000,2196,605,23,0 +A2,exact_identifier,"FilterLevel",rtk_grep,3,25000,902,288,25,0 +A2,exact_identifier,"FilterLevel",rtk_rgai,3,10000,691,223,32,0 +A2,exact_identifier,"FilterLevel",head_n,3,0,2196,605,23,0 +A2,exact_identifier,"FilterLevel",grep,4,5000,2196,605,23,0 +A2,exact_identifier,"FilterLevel",rtk_grep,4,22000,902,288,25,0 +A2,exact_identifier,"FilterLevel",rtk_rgai,4,10000,691,223,32,0 +A2,exact_identifier,"FilterLevel",head_n,4,0,2196,605,23,0 +A2,exact_identifier,"FilterLevel",grep,5,5000,2196,605,23,0 +A2,exact_identifier,"FilterLevel",rtk_grep,5,25000,902,288,25,0 +A2,exact_identifier,"FilterLevel",rtk_rgai,5,10000,691,223,32,0 +A2,exact_identifier,"FilterLevel",head_n,5,0,2196,605,23,0 +A3,exact_identifier,"classify_command",grep,1,7000,2524,626,22,0 +A3,exact_identifier,"classify_command",rtk_grep,1,24000,817,225,20,0 +A3,exact_identifier,"classify_command",rtk_rgai,1,10000,782,200,25,0 +A3,exact_identifier,"classify_command",head_n,1,0,2524,626,22,0 +A3,exact_identifier,"classify_command",grep,2,7000,2524,626,22,0 +A3,exact_identifier,"classify_command",rtk_grep,2,24000,817,225,20,0 +A3,exact_identifier,"classify_command",rtk_rgai,2,11000,782,200,25,0 +A3,exact_identifier,"classify_command",head_n,2,0,2524,626,22,0 +A3,exact_identifier,"classify_command",grep,3,7000,2524,626,22,0 +A3,exact_identifier,"classify_command",rtk_grep,3,24000,817,225,20,0 +A3,exact_identifier,"classify_command",rtk_rgai,3,10000,782,200,25,0 +A3,exact_identifier,"classify_command",head_n,3,0,2524,626,22,0 +A3,exact_identifier,"classify_command",grep,4,7000,2524,626,22,0 +A3,exact_identifier,"classify_command",rtk_grep,4,23000,817,225,20,0 +A3,exact_identifier,"classify_command",rtk_rgai,4,11000,782,200,25,0 +A3,exact_identifier,"classify_command",head_n,4,0,2524,626,22,0 +A3,exact_identifier,"classify_command",grep,5,7000,2524,626,22,0 +A3,exact_identifier,"classify_command",rtk_grep,5,23000,817,225,20,0 +A3,exact_identifier,"classify_command",rtk_rgai,5,11000,782,200,25,0 +A3,exact_identifier,"classify_command",head_n,5,0,2524,626,22,0 +A4,exact_identifier,"package_manager_exec",grep,1,7000,918,260,9,0 +A4,exact_identifier,"package_manager_exec",rtk_grep,1,24000,797,246,21,0 +A4,exact_identifier,"package_manager_exec",rtk_rgai,1,11000,1370,381,44,0 +A4,exact_identifier,"package_manager_exec",head_n,1,0,918,260,9,0 +A4,exact_identifier,"package_manager_exec",grep,2,7000,918,260,9,0 +A4,exact_identifier,"package_manager_exec",rtk_grep,2,26000,797,246,21,0 +A4,exact_identifier,"package_manager_exec",rtk_rgai,2,11000,1370,381,44,0 +A4,exact_identifier,"package_manager_exec",head_n,2,0,918,260,9,0 +A4,exact_identifier,"package_manager_exec",grep,3,8000,918,260,9,0 +A4,exact_identifier,"package_manager_exec",rtk_grep,3,24000,797,246,21,0 +A4,exact_identifier,"package_manager_exec",rtk_rgai,3,11000,1370,381,44,0 +A4,exact_identifier,"package_manager_exec",head_n,3,0,918,260,9,0 +A4,exact_identifier,"package_manager_exec",grep,4,7000,918,260,9,0 +A4,exact_identifier,"package_manager_exec",rtk_grep,4,25000,797,246,21,0 +A4,exact_identifier,"package_manager_exec",rtk_rgai,4,10000,1370,381,44,0 +A4,exact_identifier,"package_manager_exec",head_n,4,0,918,260,9,0 +A4,exact_identifier,"package_manager_exec",grep,5,7000,918,260,9,0 +A4,exact_identifier,"package_manager_exec",rtk_grep,5,26000,797,246,21,0 +A4,exact_identifier,"package_manager_exec",rtk_rgai,5,11000,1370,381,44,0 +A4,exact_identifier,"package_manager_exec",head_n,5,0,918,260,9,0 +A5,exact_identifier,"strip_ansi",grep,1,8000,1852,539,20,0 +A5,exact_identifier,"strip_ansi",rtk_grep,1,22000,1197,388,33,0 +A5,exact_identifier,"strip_ansi",rtk_rgai,1,10000,1264,425,51,0 +A5,exact_identifier,"strip_ansi",head_n,1,0,1852,539,20,0 +A5,exact_identifier,"strip_ansi",grep,2,8000,1852,539,20,0 +A5,exact_identifier,"strip_ansi",rtk_grep,2,24000,1197,388,33,0 +A5,exact_identifier,"strip_ansi",rtk_rgai,2,11000,1264,425,51,0 +A5,exact_identifier,"strip_ansi",head_n,2,0,1852,539,20,0 +A5,exact_identifier,"strip_ansi",grep,3,8000,1852,539,20,0 +A5,exact_identifier,"strip_ansi",rtk_grep,3,25000,1197,388,33,0 +A5,exact_identifier,"strip_ansi",rtk_rgai,3,10000,1264,425,51,0 +A5,exact_identifier,"strip_ansi",head_n,3,0,1852,539,20,0 +A5,exact_identifier,"strip_ansi",grep,4,8000,1852,539,20,0 +A5,exact_identifier,"strip_ansi",rtk_grep,4,24000,1197,388,33,0 +A5,exact_identifier,"strip_ansi",rtk_rgai,4,10000,1264,425,51,0 +A5,exact_identifier,"strip_ansi",head_n,4,0,1852,539,20,0 +A5,exact_identifier,"strip_ansi",grep,5,7000,1852,539,20,0 +A5,exact_identifier,"strip_ansi",rtk_grep,5,25000,1197,388,33,0 +A5,exact_identifier,"strip_ansi",rtk_rgai,5,11000,1264,425,51,0 +A5,exact_identifier,"strip_ansi",head_n,5,0,1852,539,20,0 +A6,exact_identifier,"HISTORY_DAYS",grep,1,5000,201,61,2,0 +A6,exact_identifier,"HISTORY_DAYS",rtk_grep,1,23000,182,66,6,0 +A6,exact_identifier,"HISTORY_DAYS",rtk_rgai,1,11000,686,208,23,0 +A6,exact_identifier,"HISTORY_DAYS",head_n,1,0,201,61,2,0 +A6,exact_identifier,"HISTORY_DAYS",grep,2,5000,201,61,2,0 +A6,exact_identifier,"HISTORY_DAYS",rtk_grep,2,23000,182,66,6,0 +A6,exact_identifier,"HISTORY_DAYS",rtk_rgai,2,12000,686,208,23,0 +A6,exact_identifier,"HISTORY_DAYS",head_n,2,0,201,61,2,0 +A6,exact_identifier,"HISTORY_DAYS",grep,3,6000,201,61,2,0 +A6,exact_identifier,"HISTORY_DAYS",rtk_grep,3,25000,182,66,6,0 +A6,exact_identifier,"HISTORY_DAYS",rtk_rgai,3,12000,686,208,23,0 +A6,exact_identifier,"HISTORY_DAYS",head_n,3,0,201,61,2,0 +A6,exact_identifier,"HISTORY_DAYS",grep,4,5000,201,61,2,0 +A6,exact_identifier,"HISTORY_DAYS",rtk_grep,4,28000,182,66,6,0 +A6,exact_identifier,"HISTORY_DAYS",rtk_rgai,4,11000,686,208,23,0 +A6,exact_identifier,"HISTORY_DAYS",head_n,4,0,201,61,2,0 +A6,exact_identifier,"HISTORY_DAYS",grep,5,5000,201,61,2,0 +A6,exact_identifier,"HISTORY_DAYS",rtk_grep,5,24000,182,66,6,0 +A6,exact_identifier,"HISTORY_DAYS",rtk_rgai,5,11000,686,208,23,0 +A6,exact_identifier,"HISTORY_DAYS",head_n,5,0,201,61,2,0 +B1,regex_pattern,"fn run\(.*verbose: u8",grep,1,7000,3128,999,27,0 +B1,regex_pattern,"fn run\(.*verbose: u8",rtk_grep,1,24000,3518,1206,83,0 +B1,regex_pattern,"fn run\(.*verbose: u8",rtk_rgai,1,13000,3264,1065,99,0 +B1,regex_pattern,"fn run\(.*verbose: u8",head_n,1,0,3128,999,27,0 +B1,regex_pattern,"fn run\(.*verbose: u8",grep,2,7000,3128,999,27,0 +B1,regex_pattern,"fn run\(.*verbose: u8",rtk_grep,2,26000,3518,1206,83,0 +B1,regex_pattern,"fn run\(.*verbose: u8",rtk_rgai,2,12000,3264,1065,99,0 +B1,regex_pattern,"fn run\(.*verbose: u8",head_n,2,0,3128,999,27,0 +B1,regex_pattern,"fn run\(.*verbose: u8",grep,3,7000,3128,999,27,0 +B1,regex_pattern,"fn run\(.*verbose: u8",rtk_grep,3,28000,3518,1206,83,0 +B1,regex_pattern,"fn run\(.*verbose: u8",rtk_rgai,3,12000,3264,1065,99,0 +B1,regex_pattern,"fn run\(.*verbose: u8",head_n,3,0,3128,999,27,0 +B1,regex_pattern,"fn run\(.*verbose: u8",grep,4,8000,3128,999,27,0 +B1,regex_pattern,"fn run\(.*verbose: u8",rtk_grep,4,25000,3518,1206,83,0 +B1,regex_pattern,"fn run\(.*verbose: u8",rtk_rgai,4,12000,3264,1065,99,0 +B1,regex_pattern,"fn run\(.*verbose: u8",head_n,4,0,3128,999,27,0 +B1,regex_pattern,"fn run\(.*verbose: u8",grep,5,7000,3128,999,27,0 +B1,regex_pattern,"fn run\(.*verbose: u8",rtk_grep,5,25000,3518,1206,83,0 +B1,regex_pattern,"fn run\(.*verbose: u8",rtk_rgai,5,13000,3264,1065,99,0 +B1,regex_pattern,"fn run\(.*verbose: u8",head_n,5,0,3128,999,27,0 +B2,regex_pattern,"timer\.track\(",grep,1,9000,10764,3338,116,0 +B2,regex_pattern,"timer\.track\(",rtk_grep,1,23000,5723,1979,158,0 +B2,regex_pattern,"timer\.track\(",rtk_rgai,1,12000,2542,803,93,0 +B2,regex_pattern,"timer\.track\(",head_n,1,0,9143,2822,100,0 +B2,regex_pattern,"timer\.track\(",grep,2,8000,10764,3338,116,0 +B2,regex_pattern,"timer\.track\(",rtk_grep,2,25000,5723,1979,158,0 +B2,regex_pattern,"timer\.track\(",rtk_rgai,2,11000,2542,803,93,0 +B2,regex_pattern,"timer\.track\(",head_n,2,0,9143,2822,100,0 +B2,regex_pattern,"timer\.track\(",grep,3,9000,10764,3338,116,0 +B2,regex_pattern,"timer\.track\(",rtk_grep,3,25000,5723,1979,158,0 +B2,regex_pattern,"timer\.track\(",rtk_rgai,3,11000,2542,803,93,0 +B2,regex_pattern,"timer\.track\(",head_n,3,0,9143,2822,100,0 +B2,regex_pattern,"timer\.track\(",grep,4,8000,10764,3338,116,0 +B2,regex_pattern,"timer\.track\(",rtk_grep,4,24000,5723,1979,158,0 +B2,regex_pattern,"timer\.track\(",rtk_rgai,4,12000,2542,803,93,0 +B2,regex_pattern,"timer\.track\(",head_n,4,0,9143,2822,100,0 +B2,regex_pattern,"timer\.track\(",grep,5,8000,10764,3338,116,0 +B2,regex_pattern,"timer\.track\(",rtk_grep,5,23000,5723,1979,158,0 +B2,regex_pattern,"timer\.track\(",rtk_rgai,5,12000,2542,803,93,0 +B2,regex_pattern,"timer\.track\(",head_n,5,0,9143,2822,100,0 +B3,regex_pattern,"\.unwrap_or\(1\)",grep,1,7000,5347,1513,48,0 +B3,regex_pattern,"\.unwrap_or\(1\)",rtk_grep,1,24000,3806,1200,87,0 +B3,regex_pattern,"\.unwrap_or\(1\)",rtk_rgai,1,11000,2777,885,106,0 +B3,regex_pattern,"\.unwrap_or\(1\)",head_n,1,0,5347,1513,48,0 +B3,regex_pattern,"\.unwrap_or\(1\)",grep,2,6000,5347,1513,48,0 +B3,regex_pattern,"\.unwrap_or\(1\)",rtk_grep,2,25000,3806,1200,87,0 +B3,regex_pattern,"\.unwrap_or\(1\)",rtk_rgai,2,11000,2777,885,106,0 +B3,regex_pattern,"\.unwrap_or\(1\)",head_n,2,0,5347,1513,48,0 +B3,regex_pattern,"\.unwrap_or\(1\)",grep,3,7000,5347,1513,48,0 +B3,regex_pattern,"\.unwrap_or\(1\)",rtk_grep,3,24000,3806,1200,87,0 +B3,regex_pattern,"\.unwrap_or\(1\)",rtk_rgai,3,11000,2777,885,106,0 +B3,regex_pattern,"\.unwrap_or\(1\)",head_n,3,0,5347,1513,48,0 +B3,regex_pattern,"\.unwrap_or\(1\)",grep,4,7000,5347,1513,48,0 +B3,regex_pattern,"\.unwrap_or\(1\)",rtk_grep,4,24000,3806,1200,87,0 +B3,regex_pattern,"\.unwrap_or\(1\)",rtk_rgai,4,11000,2777,885,106,0 +B3,regex_pattern,"\.unwrap_or\(1\)",head_n,4,0,5347,1513,48,0 +B3,regex_pattern,"\.unwrap_or\(1\)",grep,5,6000,5347,1513,48,0 +B3,regex_pattern,"\.unwrap_or\(1\)",rtk_grep,5,31000,3806,1200,87,0 +B3,regex_pattern,"\.unwrap_or\(1\)",rtk_rgai,5,15000,2777,885,106,0 +B3,regex_pattern,"\.unwrap_or\(1\)",head_n,5,0,5347,1513,48,0 +B4,regex_pattern,"#\[cfg\(test\)\]",grep,1,6000,2605,845,41,0 +B4,regex_pattern,"#\[cfg\(test\)\]",rtk_grep,1,26000,3098,1142,125,0 +B4,regex_pattern,"#\[cfg\(test\)\]",rtk_rgai,1,11000,2247,716,101,0 +B4,regex_pattern,"#\[cfg\(test\)\]",head_n,1,0,2605,845,41,0 +B4,regex_pattern,"#\[cfg\(test\)\]",grep,2,5000,2605,845,41,0 +B4,regex_pattern,"#\[cfg\(test\)\]",rtk_grep,2,25000,3098,1142,125,0 +B4,regex_pattern,"#\[cfg\(test\)\]",rtk_rgai,2,11000,2247,716,101,0 +B4,regex_pattern,"#\[cfg\(test\)\]",head_n,2,0,2605,845,41,0 +B4,regex_pattern,"#\[cfg\(test\)\]",grep,3,5000,2605,845,41,0 +B4,regex_pattern,"#\[cfg\(test\)\]",rtk_grep,3,25000,3098,1142,125,0 +B4,regex_pattern,"#\[cfg\(test\)\]",rtk_rgai,3,11000,2247,716,101,0 +B4,regex_pattern,"#\[cfg\(test\)\]",head_n,3,0,2605,845,41,0 +B4,regex_pattern,"#\[cfg\(test\)\]",grep,4,5000,2605,845,41,0 +B4,regex_pattern,"#\[cfg\(test\)\]",rtk_grep,4,24000,3098,1142,125,0 +B4,regex_pattern,"#\[cfg\(test\)\]",rtk_rgai,4,11000,2247,716,101,0 +B4,regex_pattern,"#\[cfg\(test\)\]",head_n,4,0,2605,845,41,0 +B4,regex_pattern,"#\[cfg\(test\)\]",grep,5,5000,2605,845,41,0 +B4,regex_pattern,"#\[cfg\(test\)\]",rtk_grep,5,24000,3098,1142,125,0 +B4,regex_pattern,"#\[cfg\(test\)\]",rtk_rgai,5,12000,2247,716,101,0 +B4,regex_pattern,"#\[cfg\(test\)\]",head_n,5,0,2605,845,41,0 +B5,regex_pattern,"HashMap 0",grep,1,6000,6540,2112,90,0 +D1,cross_file,"verbose > 0",rtk_grep,1,25000,4307,1634,162,0 +D1,cross_file,"verbose > 0",rtk_rgai,1,11000,2238,709,97,0 +D1,cross_file,"verbose > 0",head_n,1,0,6540,2112,90,0 +D1,cross_file,"verbose > 0",grep,2,5000,6540,2112,90,0 +D1,cross_file,"verbose > 0",rtk_grep,2,25000,4307,1634,162,0 +D1,cross_file,"verbose > 0",rtk_rgai,2,11000,2238,709,97,0 +D1,cross_file,"verbose > 0",head_n,2,0,6540,2112,90,0 +D1,cross_file,"verbose > 0",grep,3,6000,6540,2112,90,0 +D1,cross_file,"verbose > 0",rtk_grep,3,25000,4307,1634,162,0 +D1,cross_file,"verbose > 0",rtk_rgai,3,11000,2238,709,97,0 +D1,cross_file,"verbose > 0",head_n,3,0,6540,2112,90,0 +D1,cross_file,"verbose > 0",grep,4,6000,6540,2112,90,0 +D1,cross_file,"verbose > 0",rtk_grep,4,26000,4307,1634,162,0 +D1,cross_file,"verbose > 0",rtk_rgai,4,11000,2238,709,97,0 +D1,cross_file,"verbose > 0",head_n,4,0,6540,2112,90,0 +D1,cross_file,"verbose > 0",grep,5,6000,6540,2112,90,0 +D1,cross_file,"verbose > 0",rtk_grep,5,24000,4307,1634,162,0 +D1,cross_file,"verbose > 0",rtk_rgai,5,11000,2238,709,97,0 +D1,cross_file,"verbose > 0",head_n,5,0,6540,2112,90,0 +D2,cross_file,"anyhow::Result",grep,1,8000,753,235,11,0 +D2,cross_file,"anyhow::Result",rtk_grep,1,24000,954,333,35,0 +D2,cross_file,"anyhow::Result",rtk_rgai,1,12000,2416,765,102,0 +D2,cross_file,"anyhow::Result",head_n,1,0,753,235,11,0 +D2,cross_file,"anyhow::Result",grep,2,8000,753,235,11,0 +D2,cross_file,"anyhow::Result",rtk_grep,2,24000,954,333,35,0 +D2,cross_file,"anyhow::Result",rtk_rgai,2,12000,2416,765,102,0 +D2,cross_file,"anyhow::Result",head_n,2,0,753,235,11,0 +D2,cross_file,"anyhow::Result",grep,3,8000,753,235,11,0 +D2,cross_file,"anyhow::Result",rtk_grep,3,23000,954,333,35,0 +D2,cross_file,"anyhow::Result",rtk_rgai,3,12000,2416,765,102,0 +D2,cross_file,"anyhow::Result",head_n,3,0,753,235,11,0 +D2,cross_file,"anyhow::Result",grep,4,8000,753,235,11,0 +D2,cross_file,"anyhow::Result",rtk_grep,4,23000,954,333,35,0 +D2,cross_file,"anyhow::Result",rtk_rgai,4,12000,2416,765,102,0 +D2,cross_file,"anyhow::Result",head_n,4,0,753,235,11,0 +D2,cross_file,"anyhow::Result",grep,5,8000,753,235,11,0 +D2,cross_file,"anyhow::Result",rtk_grep,5,24000,954,333,35,0 +D2,cross_file,"anyhow::Result",rtk_rgai,5,11000,2416,765,102,0 +D2,cross_file,"anyhow::Result",head_n,5,0,753,235,11,0 +D3,cross_file,"process::exit",grep,1,7000,5234,1474,47,0 +D3,cross_file,"process::exit",rtk_grep,1,24000,3682,1154,84,0 +D3,cross_file,"process::exit",rtk_rgai,1,12000,2538,804,106,0 +D3,cross_file,"process::exit",head_n,1,0,5234,1474,47,0 +D3,cross_file,"process::exit",grep,2,7000,5234,1474,47,0 +D3,cross_file,"process::exit",rtk_grep,2,24000,3682,1154,84,0 +D3,cross_file,"process::exit",rtk_rgai,2,12000,2538,804,106,0 +D3,cross_file,"process::exit",head_n,2,0,5234,1474,47,0 +D3,cross_file,"process::exit",grep,3,8000,5234,1474,47,0 +D3,cross_file,"process::exit",rtk_grep,3,24000,3682,1154,84,0 +D3,cross_file,"process::exit",rtk_rgai,3,12000,2538,804,106,0 +D3,cross_file,"process::exit",head_n,3,0,5234,1474,47,0 +D3,cross_file,"process::exit",grep,4,7000,5234,1474,47,0 +D3,cross_file,"process::exit",rtk_grep,4,24000,3682,1154,84,0 +D3,cross_file,"process::exit",rtk_rgai,4,12000,2538,804,106,0 +D3,cross_file,"process::exit",head_n,4,0,5234,1474,47,0 +D3,cross_file,"process::exit",grep,5,7000,5234,1474,47,0 +D3,cross_file,"process::exit",rtk_grep,5,24000,3682,1154,84,0 +D3,cross_file,"process::exit",rtk_rgai,5,13000,2538,804,106,0 +D3,cross_file,"process::exit",head_n,5,0,5234,1474,47,0 +D4,cross_file,"Command::new",grep,1,5000,9867,2999,111,0 +D4,cross_file,"Command::new",rtk_grep,1,24000,5321,1790,145,0 +D4,cross_file,"Command::new",rtk_rgai,1,11000,2283,769,102,0 +D4,cross_file,"Command::new",head_n,1,0,8937,2700,100,0 +D4,cross_file,"Command::new",grep,2,5000,9867,2999,111,0 +D4,cross_file,"Command::new",rtk_grep,2,25000,5321,1790,145,0 +D4,cross_file,"Command::new",rtk_rgai,2,12000,2283,769,102,0 +D4,cross_file,"Command::new",head_n,2,0,8937,2700,100,0 +D4,cross_file,"Command::new",grep,3,6000,9867,2999,111,0 +D4,cross_file,"Command::new",rtk_grep,3,26000,5321,1790,145,0 +D4,cross_file,"Command::new",rtk_rgai,3,11000,2283,769,102,0 +D4,cross_file,"Command::new",head_n,3,0,8937,2700,100,0 +D4,cross_file,"Command::new",grep,4,5000,9867,2999,111,0 +D4,cross_file,"Command::new",rtk_grep,4,25000,5321,1790,145,0 +D4,cross_file,"Command::new",rtk_rgai,4,12000,2283,769,102,0 +D4,cross_file,"Command::new",head_n,4,0,8937,2700,100,0 +D4,cross_file,"Command::new",grep,5,5000,9867,2999,111,0 +D4,cross_file,"Command::new",rtk_grep,5,24000,5321,1790,145,0 +D4,cross_file,"Command::new",rtk_rgai,5,12000,2283,769,102,0 +D4,cross_file,"Command::new",head_n,5,0,8937,2700,100,0 +D5,cross_file,"from_utf8_lossy",grep,1,7000,17304,5038,157,0 +D5,cross_file,"from_utf8_lossy",rtk_grep,1,23000,8386,2572,168,0 +D5,cross_file,"from_utf8_lossy",rtk_rgai,1,11000,2767,867,94,0 +D5,cross_file,"from_utf8_lossy",head_n,1,0,10775,3127,100,0 +D5,cross_file,"from_utf8_lossy",grep,2,8000,17304,5038,157,0 +D5,cross_file,"from_utf8_lossy",rtk_grep,2,25000,8386,2572,168,0 +D5,cross_file,"from_utf8_lossy",rtk_rgai,2,11000,2767,867,94,0 +D5,cross_file,"from_utf8_lossy",head_n,2,0,10775,3127,100,0 +D5,cross_file,"from_utf8_lossy",grep,3,8000,17304,5038,157,0 +D5,cross_file,"from_utf8_lossy",rtk_grep,3,27000,8386,2572,168,0 +D5,cross_file,"from_utf8_lossy",rtk_rgai,3,11000,2767,867,94,0 +D5,cross_file,"from_utf8_lossy",head_n,3,0,10775,3127,100,0 +D5,cross_file,"from_utf8_lossy",grep,4,7000,17304,5038,157,0 +D5,cross_file,"from_utf8_lossy",rtk_grep,4,25000,8386,2572,168,0 +D5,cross_file,"from_utf8_lossy",rtk_rgai,4,11000,2767,867,94,0 +D5,cross_file,"from_utf8_lossy",head_n,4,0,10775,3127,100,0 +D5,cross_file,"from_utf8_lossy",grep,5,7000,17304,5038,157,0 +D5,cross_file,"from_utf8_lossy",rtk_grep,5,26000,8386,2572,168,0 +D5,cross_file,"from_utf8_lossy",rtk_rgai,5,12000,2767,867,94,0 +D5,cross_file,"from_utf8_lossy",head_n,5,0,10775,3127,100,0 +E1,edge_case,"the",grep,1,9000,19971,5421,178,0 +E1,edge_case,"the",rtk_grep,1,28000,11273,3399,239,0 +E1,edge_case,"the",rtk_rgai,1,11000,2359,779,106,0 +E1,edge_case,"the",head_n,1,0,11771,3170,100,0 +E1,edge_case,"the",grep,2,8000,19971,5421,178,0 +E1,edge_case,"the",rtk_grep,2,26000,11273,3399,239,0 +E1,edge_case,"the",rtk_rgai,2,11000,2359,779,106,0 +E1,edge_case,"the",head_n,2,0,11771,3170,100,0 +E1,edge_case,"the",grep,3,10000,19971,5421,178,0 +E1,edge_case,"the",rtk_grep,3,24000,11273,3399,239,0 +E1,edge_case,"the",rtk_rgai,3,10000,2359,779,106,0 +E1,edge_case,"the",head_n,3,0,11771,3170,100,0 +E1,edge_case,"the",grep,4,8000,19971,5421,178,0 +E1,edge_case,"the",rtk_grep,4,26000,11273,3399,239,0 +E1,edge_case,"the",rtk_rgai,4,10000,2359,779,106,0 +E1,edge_case,"the",head_n,4,0,11771,3170,100,0 +E1,edge_case,"the",grep,5,8000,19971,5421,178,0 +E1,edge_case,"the",rtk_grep,5,27000,11273,3399,239,0 +E1,edge_case,"the",rtk_rgai,5,10000,2359,779,106,0 +E1,edge_case,"the",head_n,5,0,11771,3170,100,0 +E2,edge_case,"fn",grep,1,7000,77939,23141,784,0 +E2,edge_case,"fn",rtk_grep,1,26000,12744,4052,264,0 +E2,edge_case,"fn",rtk_rgai,1,10000,2733,872,101,0 +E2,edge_case,"fn",head_n,1,0,10320,3103,100,0 +E2,edge_case,"fn",grep,2,6000,77939,23141,784,0 +E2,edge_case,"fn",rtk_grep,2,24000,12744,4052,264,0 +E2,edge_case,"fn",rtk_rgai,2,10000,2733,872,101,0 +E2,edge_case,"fn",head_n,2,0,10320,3103,100,0 +E2,edge_case,"fn",grep,3,8000,77939,23141,784,0 +E2,edge_case,"fn",rtk_grep,3,26000,12744,4052,264,0 +E2,edge_case,"fn",rtk_rgai,3,10000,2733,872,101,0 +E2,edge_case,"fn",head_n,3,0,10320,3103,100,0 +E2,edge_case,"fn",grep,4,7000,77939,23141,784,0 +E2,edge_case,"fn",rtk_grep,4,24000,12744,4052,264,0 +E2,edge_case,"fn",rtk_rgai,4,10000,2733,872,101,0 +E2,edge_case,"fn",head_n,4,0,10320,3103,100,0 +E2,edge_case,"fn",grep,5,6000,77939,23141,784,0 +E2,edge_case,"fn",rtk_grep,5,27000,12744,4052,264,0 +E2,edge_case,"fn",rtk_rgai,5,10000,2733,872,101,0 +E2,edge_case,"fn",head_n,5,0,10320,3103,100,0 +E3,edge_case,"error handling retry backoff",grep,1,9000,0,0,0,1 +E3,edge_case,"error handling retry backoff",rtk_grep,1,24000,42,13,1,0 +E3,edge_case,"error handling retry backoff",rtk_rgai,1,14000,2340,756,102,0 +E3,edge_case,"error handling retry backoff",head_n,1,0,0,0,0,0 +E3,edge_case,"error handling retry backoff",grep,2,12000,0,0,0,1 +E3,edge_case,"error handling retry backoff",rtk_grep,2,27000,42,13,1,0 +E3,edge_case,"error handling retry backoff",rtk_rgai,2,13000,2340,756,102,0 +E3,edge_case,"error handling retry backoff",head_n,2,0,0,0,0,0 +E3,edge_case,"error handling retry backoff",grep,3,9000,0,0,0,1 +E3,edge_case,"error handling retry backoff",rtk_grep,3,28000,42,13,1,0 +E3,edge_case,"error handling retry backoff",rtk_rgai,3,13000,2340,756,102,0 +E3,edge_case,"error handling retry backoff",head_n,3,0,0,0,0,0 +E3,edge_case,"error handling retry backoff",grep,4,9000,0,0,0,1 +E3,edge_case,"error handling retry backoff",rtk_grep,4,23000,42,13,1,0 +E3,edge_case,"error handling retry backoff",rtk_rgai,4,13000,2340,756,102,0 +E3,edge_case,"error handling retry backoff",head_n,4,0,0,0,0,0 +E3,edge_case,"error handling retry backoff",grep,5,9000,0,0,0,1 +E3,edge_case,"error handling retry backoff",rtk_grep,5,25000,42,13,1,0 +E3,edge_case,"error handling retry backoff",rtk_rgai,5,14000,2340,756,102,0 +E3,edge_case,"error handling retry backoff",head_n,5,0,0,0,0,0 diff --git a/benchmarks/tests/__init__.py b/benchmarks/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/benchmarks/tests/test_analyze_code.py b/benchmarks/tests/test_analyze_code.py new file mode 100644 index 0000000..d769e7b --- /dev/null +++ b/benchmarks/tests/test_analyze_code.py @@ -0,0 +1,466 @@ +""" +Tests for analyze_code.py benchmark analyzer. + +Covers: + - median_val computation + - is_valid_exit semantics + - extract_filenames from various output formats + - compute_gold_hit_rate accuracy + - is_miss detection (critical rule) + - format_te / format_pct output + - compute_metrics end-to-end with mock data +""" + +from __future__ import annotations + +import json +import tempfile +import unittest +from pathlib import Path +from unittest.mock import patch + +import sys + +# Add parent dir to path so we can import analyze_code +sys.path.insert(0, str(Path(__file__).resolve().parent.parent)) + +import analyze_code as ac + + +class TestMedianVal(unittest.TestCase): + def test_odd_count(self): + self.assertEqual(ac.median_val([3, 1, 2]), 2.0) + + def test_even_count(self): + self.assertEqual(ac.median_val([1, 2, 3, 4]), 2.5) + + def test_single(self): + self.assertEqual(ac.median_val([42]), 42.0) + + def test_empty(self): + self.assertEqual(ac.median_val([]), 0.0) + + def test_already_sorted(self): + self.assertEqual(ac.median_val([10, 20, 30, 40, 50]), 30.0) + + def test_duplicates(self): + self.assertEqual(ac.median_val([5, 5, 5, 5, 5]), 5.0) + + +class TestIsValidExit(unittest.TestCase): + def test_exit_0_valid(self): + self.assertTrue(ac.is_valid_exit(0)) + + def test_exit_1_valid(self): + """exit=1 means 'no matches' for grep — still valid.""" + self.assertTrue(ac.is_valid_exit(1)) + + def test_exit_2_invalid(self): + """exit>=2 means execution error.""" + self.assertFalse(ac.is_valid_exit(2)) + + def test_exit_127_invalid(self): + self.assertFalse(ac.is_valid_exit(127)) + + +class TestExtractFilenames(unittest.TestCase): + def test_grep_output(self): + """Standard grep -rn output format.""" + text = ( + "src/tracking.rs:42:pub struct TimedExecution {\n" + "src/main.rs:100: let timer = TimedExecution::new();\n" + "src/discover/registry.rs:77:const RULES: &[RtkRule] = &[\n" + ) + filenames = ac.extract_filenames(text) + self.assertIn("tracking.rs", filenames) + self.assertIn("main.rs", filenames) + self.assertIn("discover/registry.rs", filenames) + + def test_rtk_file_headers(self): + """RTK grouped output headers.""" + text = ( + "📄 /Users/andrew/Programming/rtk/src/tracking.rs (1):\n" + "📄 /.../discover/registry.rs [9.1]\n" + ) + filenames = ac.extract_filenames(text) + self.assertIn("tracking.rs", filenames) + self.assertIn("discover/registry.rs", filenames) + + def test_no_filenames(self): + """Text with no .rs files.""" + text = "no rust files here\njust plain text" + filenames = ac.extract_filenames(text) + self.assertEqual(len(filenames), 0) + + def test_nested_path(self): + """Nested directory paths.""" + text = "src/parser/mod.rs:1:pub mod types;" + filenames = ac.extract_filenames(text) + self.assertIn("parser/mod.rs", filenames) + + def test_absolute_path_normalization(self): + text = ( + "/Users/andrew/Programming/rtk/src/tracking.rs:42:code\n" + "/Users/andrew/Programming/rtk/src/discover/registry.rs:77:code\n" + ) + filenames = ac.extract_filenames(text) + self.assertIn("tracking.rs", filenames) + self.assertIn("discover/registry.rs", filenames) + + def test_deduplication(self): + """Same file appearing multiple times.""" + text = ( + "src/git.rs:10:code\n" + "src/git.rs:20:more code\n" + "src/git.rs:30:even more\n" + ) + filenames = ac.extract_filenames(text) + self.assertEqual(filenames.count("git.rs") if isinstance(filenames, list) else 1, 1) + self.assertIn("git.rs", filenames) + + def test_does_not_parse_rs_inside_code_snippet(self): + text = ' 565: classify_command("cat src/main.rs"),' + filenames = ac.extract_filenames(text) + self.assertEqual(len(filenames), 0) + + +class TestComputeGoldHitRate(unittest.TestCase): + def test_all_found(self): + sample = "src/tracking.rs:1:code\nsrc/main.rs:2:code\n" + gold = ["tracking.rs", "main.rs"] + self.assertAlmostEqual(ac.compute_gold_hit_rate(sample, gold), 1.0) + + def test_partial_found(self): + sample = "src/tracking.rs:1:code\nsrc/utils.rs:2:code\n" + gold = ["tracking.rs", "main.rs"] + self.assertAlmostEqual(ac.compute_gold_hit_rate(sample, gold), 0.5) + + def test_none_found(self): + sample = "src/utils.rs:1:code\n" + gold = ["tracking.rs", "main.rs"] + self.assertAlmostEqual(ac.compute_gold_hit_rate(sample, gold), 0.0) + + def test_empty_gold_files(self): + """No gold files => N/A for hit-rate.""" + sample = "src/anything.rs:1:code\n" + self.assertIsNone(ac.compute_gold_hit_rate(sample, [])) + + def test_empty_sample(self): + gold = ["tracking.rs"] + self.assertAlmostEqual(ac.compute_gold_hit_rate("", gold), 0.0) + + def test_nested_gold_files(self): + sample = "src/discover/registry.rs:77:const RULES\n" + gold = ["discover/registry.rs"] + self.assertAlmostEqual(ac.compute_gold_hit_rate(sample, gold), 1.0) + + +class TestIsMiss(unittest.TestCase): + def test_zero_results_expects_results(self): + """0 results when gold expects results → MISS.""" + self.assertTrue(ac.is_miss(0, True)) + + def test_zero_results_expects_nothing(self): + """0 results when gold expects nothing → NOT miss.""" + self.assertFalse(ac.is_miss(0, False)) + + def test_has_results_expects_results(self): + """Has results when expected → NOT miss.""" + self.assertFalse(ac.is_miss(42, True)) + + def test_has_results_expects_nothing(self): + """Has results when nothing expected → NOT miss (unexpected but not MISS).""" + self.assertFalse(ac.is_miss(5, False)) + + +class TestFormatFunctions(unittest.TestCase): + def test_format_te_normal(self): + self.assertEqual(ac.format_te(0.123, False), "0.123") + + def test_format_te_miss(self): + self.assertEqual(ac.format_te(0.5, True), "MISS") + + def test_format_te_none(self): + self.assertEqual(ac.format_te(None, False), "N/A") + + def test_format_pct_savings(self): + self.assertEqual(ac.format_pct(0.3, False), "70.0%") + + def test_format_pct_miss(self): + self.assertEqual(ac.format_pct(0.3, True), "MISS") + + def test_format_pct_expansion(self): + """TE > 1.0 means output is larger than grep baseline.""" + self.assertEqual(ac.format_pct(1.5, False), "-50.0%") + + def test_format_gold_full(self): + self.assertEqual(ac.format_gold(1.0, 10, 5), "100% (10/5)") + + def test_format_gold_partial(self): + self.assertEqual(ac.format_gold(0.6, 3, 8), "60% (3/8)") + + def test_format_gold_none(self): + self.assertEqual(ac.format_gold(None, 0, 0), "N/A") + + def test_format_gold_none_with_min(self): + self.assertEqual(ac.format_gold(None, 2, 10), "N/A (2/10)") + + def test_format_timing_microseconds(self): + self.assertEqual(ac.format_timing(500), "500μs") + + def test_format_timing_milliseconds(self): + self.assertEqual(ac.format_timing(5000), "5.0ms") + + def test_format_timing_seconds(self): + self.assertEqual(ac.format_timing(2_500_000), "2.50s") + + +class TestComputeMetrics(unittest.TestCase): + """End-to-end test of compute_metrics with synthetic data.""" + + def _make_rows(self, tid, tool, runs=5, time=1000, output_bytes=500, + output_tokens=100, result_count=10, exit_code=0): + """Helper to generate mock CSV rows.""" + return [ + { + "test_id": tid, + "category": "exact_identifier", + "query": f'"{tid} query"', + "tool": tool, + "run": i + 1, + "time_us": time + i * 10, + "output_bytes": output_bytes, + "output_tokens": output_tokens, + "result_count": result_count, + "exit_code": exit_code, + } + for i in range(runs) + ] + + def test_basic_metrics(self): + """Verify TE computation for a simple case.""" + gold = { + "T1": { + "query": "test", + "category": "exact_identifier", + "gold_files": [], + "gold_min_files": 0, + "expect_results": True, + } + } + rows = ( + self._make_rows("T1", "grep", output_bytes=1000, output_tokens=1000, result_count=50) + + self._make_rows("T1", "rtk_grep", output_bytes=300, output_tokens=300, result_count=20) + + self._make_rows("T1", "rtk_rgai", output_bytes=200, output_tokens=200, result_count=10) + ) + + with patch.object(ac, "load_quality_sample", return_value=""): + metrics = ac.compute_metrics(rows, gold) + + self.assertEqual(len(metrics), 1) + m = metrics[0] + # TE = rtk_grep_tokens / grep_tokens = 300/1000 = 0.3 + self.assertAlmostEqual(m["rtk_grep_te"], 0.3) + # TE = rtk_rgai_tokens / grep_tokens = 200/1000 = 0.2 + self.assertAlmostEqual(m["rtk_rgai_te"], 0.2) + + def test_miss_detection(self): + """0 result count with expect_results=True → MISS.""" + gold = { + "T2": { + "query": "test", + "category": "semantic_intent", + "gold_files": ["tracking.rs"], + "gold_min_files": 1, + "expect_results": True, + } + } + rows = ( + self._make_rows("T2", "grep", output_bytes=0, result_count=0) + + self._make_rows("T2", "rtk_grep", output_bytes=0, result_count=0) + + self._make_rows("T2", "rtk_rgai", output_bytes=500, result_count=5) + ) + + with patch.object(ac, "load_quality_sample", return_value=""): + metrics = ac.compute_metrics(rows, gold) + + m = metrics[0] + self.assertTrue(m["grep_miss"]) + self.assertTrue(m["rtk_grep_miss"]) + self.assertFalse(m["rtk_rgai_miss"]) + + def test_miss_detection_with_rtk_zero_marker(self): + """rtk '0 for' marker should force effective result_count=0.""" + gold = { + "T2B": { + "query": "semantic query", + "category": "semantic_intent", + "gold_files": ["tracking.rs"], + "gold_min_files": 1, + "expect_results": True, + } + } + rows = ( + self._make_rows("T2B", "grep", output_bytes=0, result_count=0) + + self._make_rows("T2B", "rtk_grep", output_bytes=42, result_count=1) + + self._make_rows("T2B", "rtk_rgai", output_bytes=2400, result_count=80) + ) + + def fake_sample(tid, tool): + if tid == "T2B" and tool == "rtk_grep": + return "🔍 0 for 'semantic query'\n" + return "" + + with patch.object(ac, "load_quality_sample", side_effect=fake_sample): + metrics = ac.compute_metrics(rows, gold) + + m = metrics[0] + self.assertEqual(m["rtk_grep_count"], 0) + self.assertTrue(m["rtk_grep_miss"]) + + def test_no_miss_when_not_expected(self): + """0 results with expect_results=False → NOT miss.""" + gold = { + "T3": { + "query": "nonexistent", + "category": "edge_case", + "gold_files": [], + "gold_min_files": 0, + "expect_results": False, + } + } + rows = ( + self._make_rows("T3", "grep", output_bytes=0, result_count=0) + + self._make_rows("T3", "rtk_grep", output_bytes=0, result_count=0) + + self._make_rows("T3", "rtk_rgai", output_bytes=0, result_count=0) + ) + + with patch.object(ac, "load_quality_sample", return_value=""): + metrics = ac.compute_metrics(rows, gold) + + m = metrics[0] + self.assertFalse(m["grep_miss"]) + self.assertFalse(m["rtk_grep_miss"]) + self.assertFalse(m["rtk_rgai_miss"]) + + def test_grep_baseline_zero_te_none(self): + """When grep baseline is 0 bytes, TE should be None.""" + gold = { + "T4": { + "query": "rare", + "category": "exact_identifier", + "gold_files": [], + "gold_min_files": 0, + "expect_results": False, + } + } + rows = ( + self._make_rows("T4", "grep", output_bytes=0, output_tokens=0, result_count=0) + + self._make_rows("T4", "rtk_grep", output_bytes=100, result_count=2) + + self._make_rows("T4", "rtk_rgai", output_bytes=50, result_count=1) + ) + + with patch.object(ac, "load_quality_sample", return_value=""): + metrics = ac.compute_metrics(rows, gold) + + m = metrics[0] + self.assertIsNone(m["rtk_grep_te"]) + self.assertIsNone(m["rtk_rgai_te"]) + + def test_zero_gold_hit_marks_low_coverage(self): + gold = { + "T5": { + "query": "semantic", + "category": "semantic_intent", + "gold_files": ["tracking.rs"], + "gold_min_files": 1, + "expect_results": True, + } + } + rows = ( + self._make_rows("T5", "grep", output_tokens=100, result_count=10) + + self._make_rows("T5", "rtk_rgai", output_tokens=20, result_count=5) + ) + + def fake_sample(tid, tool): + if tool == "grep": + return "src/tracking.rs:1:code\n" + if tool == "rtk_rgai": + return "📄 src/utils.rs [10.0]\n" + return "" + + with patch.object(ac, "load_quality_sample", side_effect=fake_sample): + metrics = ac.compute_metrics(rows, gold) + + m = metrics[0] + self.assertTrue(m["rtk_rgai_low_coverage"]) + + +class TestGoldStandardsIntegrity(unittest.TestCase): + """Verify gold_standards.json is well-formed.""" + + def setUp(self): + gold_path = Path(__file__).resolve().parent.parent / "gold_standards.json" + with open(gold_path, encoding="utf-8") as f: + self.data = json.load(f) + self.queries = self.data["queries"] + + def test_has_metadata(self): + self.assertIn("metadata", self.data) + self.assertIn("pinned_commit", self.data["metadata"]) + + def test_query_count(self): + """Should have exactly 30 queries.""" + self.assertEqual(len(self.queries), 30) + + def test_category_distribution(self): + """A=6, B=6, C=10, D=5, E=3.""" + cats = [q["category"] for q in self.queries.values()] + self.assertEqual(cats.count("exact_identifier"), 6) + self.assertEqual(cats.count("regex_pattern"), 6) + self.assertEqual(cats.count("semantic_intent"), 10) + self.assertEqual(cats.count("cross_file"), 5) + self.assertEqual(cats.count("edge_case"), 3) + + def test_required_fields(self): + """Every query has required fields.""" + required = {"query", "category", "grep_flags", "gold_files", + "gold_min_files", "expect_results", "notes"} + for tid, q in self.queries.items(): + for field in required: + self.assertIn( + field, q, + f"Query {tid} missing field '{field}'" + ) + + def test_id_prefix_matches_category(self): + """A* → exact_identifier, B* → regex_pattern, etc.""" + prefix_map = { + "A": "exact_identifier", + "B": "regex_pattern", + "C": "semantic_intent", + "D": "cross_file", + "E": "edge_case", + } + for tid, q in self.queries.items(): + expected_cat = prefix_map.get(tid[0]) + self.assertEqual( + q["category"], expected_cat, + f"Query {tid} has category '{q['category']}' " + f"but expected '{expected_cat}'" + ) + + def test_e3_expects_no_results(self): + """E3 (nonexistent phrase) should expect no results.""" + self.assertFalse(self.queries["E3"]["expect_results"]) + + def test_gold_files_are_lists(self): + for tid, q in self.queries.items(): + self.assertIsInstance( + q["gold_files"], list, + f"Query {tid} gold_files is not a list" + ) + + +if __name__ == "__main__": + unittest.main() diff --git a/docs/TROUBLESHOOTING.md b/docs/TROUBLESHOOTING.md index 64d4576..01d8b2f 100644 --- a/docs/TROUBLESHOOTING.md +++ b/docs/TROUBLESHOOTING.md @@ -165,6 +165,15 @@ Then add to `~/.claude/settings.json` (replace `~` with full path): **Note**: Use absolute path in `settings.json`, not `~/.claude/...` +### Search Priority + +**Search priority: rgai > rg > grep.** + +- Use `rtk rgai` first for semantic/intention-based discovery. +- Use `rtk grep` for exact/regex matching. +- `rtk grep` internally follows `rg -> grep` backend fallback. +- If you need fully raw output for debugging, use `rtk proxy `. + --- ## Problem: "command not found: rtk" after installation diff --git a/hooks/rtk-awareness.md b/hooks/rtk-awareness.md index 0eaf3d5..809407b 100644 --- a/hooks/rtk-awareness.md +++ b/hooks/rtk-awareness.md @@ -25,5 +25,22 @@ which rtk # Verify correct binary All other commands are automatically rewritten by the Claude Code hook. Example: `git status` → `rtk git status` (transparent, 0 tokens overhead) +Example: `grepai search "auth token refresh"` → `rtk rgai "auth token refresh"` + +## Search Priority Policy (MANDATORY) + +Search priority (mandatory): rgai > rg > grep. + +- `rtk rgai` — semantic/intention-based discovery (first choice) +- `rtk grep` — exact/regex matching (second choice, internal rg -> grep fallback) +- Native Grep tool — only if rtk commands are unavailable or broken + +## Semantic Search + +```bash +rtk rgai "auth token refresh" # Intent-aware code search +rtk rgai auth token refresh --compact # Unquoted multi-word query +rtk rgai "auth token refresh" --json # Machine-readable output +``` Refer to CLAUDE.md for full command reference. diff --git a/hooks/rtk-rewrite.sh b/hooks/rtk-rewrite.sh index 59e02ca..a62f23b 100644 --- a/hooks/rtk-rewrite.sh +++ b/hooks/rtk-rewrite.sh @@ -2,6 +2,7 @@ # RTK auto-rewrite hook for Claude Code PreToolUse:Bash # Transparently rewrites raw commands to their rtk equivalents. # Outputs JSON with updatedInput to modify the command before execution. +# Source of truth: hooks/rtk-rewrite.sh (keep .claude/hooks copy in sync) # Guards: skip silently if dependencies missing if ! command -v rtk &>/dev/null || ! command -v jq &>/dev/null; then @@ -46,37 +47,62 @@ fi REWRITTEN="" # --- Git commands --- -if echo "$MATCH_CMD" | grep -qE '^git[[:space:]]'; then - GIT_SUBCMD=$(echo "$MATCH_CMD" | sed -E \ - -e 's/^git[[:space:]]+//' \ - -e 's/(-C|-c)[[:space:]]+[^[:space:]]+[[:space:]]*//g' \ - -e 's/--[a-z-]+=[^[:space:]]+[[:space:]]*//g' \ - -e 's/--(no-pager|no-optional-locks|bare|literal-pathspecs)[[:space:]]*//g' \ - -e 's/^[[:space:]]+//') - case "$GIT_SUBCMD" in - status|status\ *|diff|diff\ *|log|log\ *|add|add\ *|commit|commit\ *|push|push\ *|pull|pull\ *|branch|branch\ *|fetch|fetch\ *|stash|stash\ *|show|show\ *) - REWRITTEN="${ENV_PREFIX}rtk $CMD_BODY" - ;; - esac +if echo "$MATCH_CMD" | grep -qE '^git[[:space:]]+status([[:space:]]|$)'; then + REWRITTEN="${ENV_PREFIX}$(echo "$CMD_BODY" | sed 's/^git status/rtk git status/')" +elif echo "$MATCH_CMD" | grep -qE '^git[[:space:]]+diff([[:space:]]|$)'; then + REWRITTEN="${ENV_PREFIX}$(echo "$CMD_BODY" | sed 's/^git diff/rtk git diff/')" +elif echo "$MATCH_CMD" | grep -qE '^git[[:space:]]+log([[:space:]]|$)'; then + REWRITTEN="${ENV_PREFIX}$(echo "$CMD_BODY" | sed 's/^git log/rtk git log/')" +elif echo "$MATCH_CMD" | grep -qE '^git[[:space:]]+add([[:space:]]|$)'; then + REWRITTEN="${ENV_PREFIX}$(echo "$CMD_BODY" | sed 's/^git add/rtk git add/')" +elif echo "$MATCH_CMD" | grep -qE '^git[[:space:]]+commit([[:space:]]|$)'; then + REWRITTEN="${ENV_PREFIX}$(echo "$CMD_BODY" | sed 's/^git commit/rtk git commit/')" +elif echo "$MATCH_CMD" | grep -qE '^git[[:space:]]+push([[:space:]]|$)'; then + REWRITTEN="${ENV_PREFIX}$(echo "$CMD_BODY" | sed 's/^git push/rtk git push/')" +elif echo "$MATCH_CMD" | grep -qE '^git[[:space:]]+pull([[:space:]]|$)'; then + REWRITTEN="${ENV_PREFIX}$(echo "$CMD_BODY" | sed 's/^git pull/rtk git pull/')" +elif echo "$MATCH_CMD" | grep -qE '^git[[:space:]]+branch([[:space:]]|$)'; then + REWRITTEN="${ENV_PREFIX}$(echo "$CMD_BODY" | sed 's/^git branch/rtk git branch/')" +elif echo "$MATCH_CMD" | grep -qE '^git[[:space:]]+fetch([[:space:]]|$)'; then + REWRITTEN="${ENV_PREFIX}$(echo "$CMD_BODY" | sed 's/^git fetch/rtk git fetch/')" +elif echo "$MATCH_CMD" | grep -qE '^git[[:space:]]+stash([[:space:]]|$)'; then + REWRITTEN="${ENV_PREFIX}$(echo "$CMD_BODY" | sed 's/^git stash/rtk git stash/')" +elif echo "$MATCH_CMD" | grep -qE '^git[[:space:]]+show([[:space:]]|$)'; then + REWRITTEN="${ENV_PREFIX}$(echo "$CMD_BODY" | sed 's/^git show/rtk git show/')" # --- GitHub CLI (added: api, release) --- elif echo "$MATCH_CMD" | grep -qE '^gh[[:space:]]+(pr|issue|run|api|release)([[:space:]]|$)'; then REWRITTEN="${ENV_PREFIX}$(echo "$CMD_BODY" | sed 's/^gh /rtk gh /')" # --- Cargo --- -elif echo "$MATCH_CMD" | grep -qE '^cargo[[:space:]]'; then - CARGO_SUBCMD=$(echo "$MATCH_CMD" | sed -E 's/^cargo[[:space:]]+(\+[^[:space:]]+[[:space:]]+)?//') - case "$CARGO_SUBCMD" in - test|test\ *|build|build\ *|clippy|clippy\ *|check|check\ *|install|install\ *|fmt|fmt\ *) - REWRITTEN="${ENV_PREFIX}rtk $CMD_BODY" - ;; - esac +elif echo "$MATCH_CMD" | grep -qE '^cargo[[:space:]]+test([[:space:]]|$)'; then + REWRITTEN="${ENV_PREFIX}$(echo "$CMD_BODY" | sed 's/^cargo test/rtk cargo test/')" +elif echo "$MATCH_CMD" | grep -qE '^cargo[[:space:]]+build([[:space:]]|$)'; then + REWRITTEN="${ENV_PREFIX}$(echo "$CMD_BODY" | sed 's/^cargo build/rtk cargo build/')" +elif echo "$MATCH_CMD" | grep -qE '^cargo[[:space:]]+clippy([[:space:]]|$)'; then + REWRITTEN="${ENV_PREFIX}$(echo "$CMD_BODY" | sed 's/^cargo clippy/rtk cargo clippy/')" +elif echo "$MATCH_CMD" | grep -qE '^cargo[[:space:]]+check([[:space:]]|$)'; then + REWRITTEN="${ENV_PREFIX}$(echo "$CMD_BODY" | sed 's/^cargo check/rtk cargo check/')" +elif echo "$MATCH_CMD" | grep -qE '^cargo[[:space:]]+install([[:space:]]|$)'; then + REWRITTEN="${ENV_PREFIX}$(echo "$CMD_BODY" | sed 's/^cargo install/rtk cargo install/')" +elif echo "$MATCH_CMD" | grep -qE '^cargo[[:space:]]+fmt([[:space:]]|$)'; then + REWRITTEN="${ENV_PREFIX}$(echo "$CMD_BODY" | sed 's/^cargo fmt/rtk cargo fmt/')" # --- File operations --- +# Search priority (mandatory): rgai > rg > grep +# Tier 1: semantic intent search (grepai/rgai) -> rtk rgai +# Tier 2: exact search via ripgrep -> rtk grep (rtk grep runs rg -> grep fallback internally) +# Tier 3: exact search via grep -> rtk grep +elif echo "$MATCH_CMD" | grep -qE '^(grepai|rgai)[[:space:]]+search([[:space:]]|$)'; then + REWRITTEN="${ENV_PREFIX}$(echo "$CMD_BODY" | sed -E 's/^(grepai|rgai)[[:space:]]+search[[:space:]]+/rtk rgai /')" +elif echo "$MATCH_CMD" | grep -qE '^rgai[[:space:]]+'; then + REWRITTEN="${ENV_PREFIX}$(echo "$CMD_BODY" | sed -E 's/^rgai[[:space:]]+/rtk rgai /')" elif echo "$MATCH_CMD" | grep -qE '^cat[[:space:]]+'; then REWRITTEN="${ENV_PREFIX}$(echo "$CMD_BODY" | sed 's/^cat /rtk read /')" -elif echo "$MATCH_CMD" | grep -qE '^(rg|grep)[[:space:]]+'; then - REWRITTEN="${ENV_PREFIX}$(echo "$CMD_BODY" | sed -E 's/^(rg|grep) /rtk grep /')" +elif echo "$MATCH_CMD" | grep -qE '^rg[[:space:]]+'; then + REWRITTEN="${ENV_PREFIX}$(echo "$CMD_BODY" | sed -E 's/^rg /rtk grep /')" +elif echo "$MATCH_CMD" | grep -qE '^grep[[:space:]]+'; then + REWRITTEN="${ENV_PREFIX}$(echo "$CMD_BODY" | sed -E 's/^grep /rtk grep /')" elif echo "$MATCH_CMD" | grep -qE '^ls([[:space:]]|$)'; then REWRITTEN="${ENV_PREFIX}$(echo "$CMD_BODY" | sed 's/^ls/rtk ls/')" elif echo "$MATCH_CMD" | grep -qE '^tree([[:space:]]|$)'; then @@ -127,32 +153,12 @@ elif echo "$MATCH_CMD" | grep -qE '^(npx[[:space:]]+)?prisma([[:space:]]|$)'; th REWRITTEN="${ENV_PREFIX}$(echo "$CMD_BODY" | sed -E 's/^(npx )?prisma/rtk prisma/')" # --- Containers (added: docker compose, docker run/build/exec, kubectl describe/apply) --- -elif echo "$MATCH_CMD" | grep -qE '^docker[[:space:]]'; then - if echo "$MATCH_CMD" | grep -qE '^docker[[:space:]]+compose([[:space:]]|$)'; then - REWRITTEN="${ENV_PREFIX}$(echo "$CMD_BODY" | sed 's/^docker /rtk docker /')" - else - DOCKER_SUBCMD=$(echo "$MATCH_CMD" | sed -E \ - -e 's/^docker[[:space:]]+//' \ - -e 's/(-H|--context|--config)[[:space:]]+[^[:space:]]+[[:space:]]*//g' \ - -e 's/--[a-z-]+=[^[:space:]]+[[:space:]]*//g' \ - -e 's/^[[:space:]]+//') - case "$DOCKER_SUBCMD" in - ps|ps\ *|images|images\ *|logs|logs\ *|run|run\ *|build|build\ *|exec|exec\ *) - REWRITTEN="${ENV_PREFIX}$(echo "$CMD_BODY" | sed 's/^docker /rtk docker /')" - ;; - esac - fi -elif echo "$MATCH_CMD" | grep -qE '^kubectl[[:space:]]'; then - KUBE_SUBCMD=$(echo "$MATCH_CMD" | sed -E \ - -e 's/^kubectl[[:space:]]+//' \ - -e 's/(--context|--kubeconfig|--namespace|-n)[[:space:]]+[^[:space:]]+[[:space:]]*//g' \ - -e 's/--[a-z-]+=[^[:space:]]+[[:space:]]*//g' \ - -e 's/^[[:space:]]+//') - case "$KUBE_SUBCMD" in - get|get\ *|logs|logs\ *|describe|describe\ *|apply|apply\ *) - REWRITTEN="${ENV_PREFIX}$(echo "$CMD_BODY" | sed 's/^kubectl /rtk kubectl /')" - ;; - esac +elif echo "$MATCH_CMD" | grep -qE '^docker[[:space:]]+compose([[:space:]]|$)'; then + REWRITTEN="${ENV_PREFIX}$(echo "$CMD_BODY" | sed 's/^docker /rtk docker /')" +elif echo "$MATCH_CMD" | grep -qE '^docker[[:space:]]+(ps|images|logs|run|build|exec)([[:space:]]|$)'; then + REWRITTEN="${ENV_PREFIX}$(echo "$CMD_BODY" | sed 's/^docker /rtk docker /')" +elif echo "$MATCH_CMD" | grep -qE '^kubectl[[:space:]]+(get|logs|describe|apply)([[:space:]]|$)'; then + REWRITTEN="${ENV_PREFIX}$(echo "$CMD_BODY" | sed 's/^kubectl /rtk kubectl /')" # --- Network --- elif echo "$MATCH_CMD" | grep -qE '^curl[[:space:]]+'; then diff --git a/hooks/test-rtk-rewrite.sh b/hooks/test-rtk-rewrite.sh index 2a68ff8..61b5b86 100755 --- a/hooks/test-rtk-rewrite.sh +++ b/hooks/test-rtk-rewrite.sh @@ -2,9 +2,11 @@ # Test suite for rtk-rewrite.sh # Feeds mock JSON through the hook and verifies the rewritten commands. # -# Usage: bash ~/.claude/hooks/test-rtk-rewrite.sh +# Usage: bash hooks/test-rtk-rewrite.sh +# Override hook path: HOOK=/path/to/rtk-rewrite.sh bash hooks/test-rtk-rewrite.sh -HOOK="$HOME/.claude/hooks/rtk-rewrite.sh" +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +HOOK="${HOOK:-$SCRIPT_DIR/rtk-rewrite.sh}" PASS=0 FAIL=0 TOTAL=0 @@ -109,6 +111,22 @@ test_rewrite "rg pattern src/" \ "rg pattern src/" \ "rtk grep pattern src/" +test_rewrite "grepai search query" \ + "grepai search auth middleware" \ + "rtk rgai auth middleware" + +test_rewrite "grepai search with flags" \ + "grepai search \"error handler\" --json --compact" \ + "rtk rgai \"error handler\" --json --compact" + +test_rewrite "rgai search query (priority over rg/grep)" \ + "rgai search auth middleware --compact" \ + "rtk rgai auth middleware --compact" + +test_rewrite "plain rgai" \ + "rgai auth middleware --json" \ + "rtk rgai auth middleware --json" + test_rewrite "cargo test" \ "cargo test" \ "rtk cargo test" @@ -149,6 +167,18 @@ test_rewrite "env + docker compose" \ "COMPOSE_PROJECT_NAME=test docker compose up -d" \ "COMPOSE_PROJECT_NAME=test rtk docker compose up -d" +test_rewrite "env + grepai search" \ + "NODE_ENV=test grepai search token refresh --json" \ + "NODE_ENV=test rtk rgai token refresh --json" + +test_rewrite "env + rg exact search" \ + "RG_IGNORE_DOT=1 rg token src/" \ + "RG_IGNORE_DOT=1 rtk grep token src/" + +test_rewrite "env + grep exact search" \ + "LC_ALL=C grep -rn token src/" \ + "LC_ALL=C rtk grep -rn token src/" + echo "" # ---- SECTION 3: New patterns ---- @@ -193,17 +223,17 @@ test_rewrite "docker exec -it db psql" \ "docker exec -it db psql" \ "rtk docker exec -it db psql" -test_rewrite "find (NOT rewritten — different arg format)" \ +test_rewrite "find with native args" \ "find . -name '*.ts'" \ - "" + "rtk find . -name '*.ts'" -test_rewrite "tree (NOT rewritten — different arg format)" \ +test_rewrite "tree with path arg" \ "tree src/" \ - "" + "rtk tree src/" -test_rewrite "wget (NOT rewritten — different arg format)" \ +test_rewrite "wget URL" \ "wget https://example.com/file" \ - "" + "rtk wget https://example.com/file" test_rewrite "gh api repos/owner/repo" \ "gh api repos/owner/repo" \ diff --git a/src/config.rs b/src/config.rs index 830ec32..0e9e361 100644 --- a/src/config.rs +++ b/src/config.rs @@ -10,6 +10,8 @@ pub struct Config { pub display: DisplayConfig, #[serde(default)] pub filters: FilterConfig, + #[serde(default)] + pub grepai: GrepaiConfig, // grepai integration settings } #[derive(Debug, Serialize, Deserialize)] @@ -69,6 +71,28 @@ impl Default for FilterConfig { } } +/// grepai external semantic search integration +#[derive(Debug, Serialize, Deserialize)] +pub struct GrepaiConfig { + /// Enable grepai delegation in `rtk rgai` (default: true) + pub enabled: bool, + /// Auto-init projects on first `rtk rgai` if grepai is installed (default: true) + pub auto_init: bool, + /// Custom binary path override (default: auto-detect via PATH) + #[serde(skip_serializing_if = "Option::is_none")] + pub binary_path: Option, +} + +impl Default for GrepaiConfig { + fn default() -> Self { + Self { + enabled: true, + auto_init: true, + binary_path: None, + } + } +} + impl Config { pub fn load() -> Result { let path = get_config_path()?; @@ -123,3 +147,16 @@ pub fn show_config() -> Result<()> { Ok(()) } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn grepai_config_defaults_are_enabled_with_auto_init() { + let cfg = Config::default(); + assert!(cfg.grepai.enabled); + assert!(cfg.grepai.auto_init); + assert_eq!(cfg.grepai.binary_path, None); + } +} diff --git a/src/gain.rs b/src/gain.rs index fae773c..dadfb66 100644 --- a/src/gain.rs +++ b/src/gain.rs @@ -5,8 +5,10 @@ use anyhow::{Context, Result}; use colored::Colorize; // added: terminal colors use serde::Serialize; use std::io::IsTerminal; // added: TTY detection for graceful degradation +use std::path::PathBuf; // added: for project path resolution pub fn run( + project: bool, // added: per-project scope flag graph: bool, history: bool, quota: bool, @@ -19,16 +21,35 @@ pub fn run( _verbose: u8, ) -> Result<()> { let tracker = Tracker::new().context("Failed to initialize tracking database")?; + let project_scope = resolve_project_scope(project)?; // added: resolve project path // Handle export formats match format { - "json" => return export_json(&tracker, daily, weekly, monthly, all), - "csv" => return export_csv(&tracker, daily, weekly, monthly, all), + "json" => { + return export_json( + &tracker, + daily, + weekly, + monthly, + all, + project_scope.as_deref(), // added: pass project scope + ); + } + "csv" => { + return export_csv( + &tracker, + daily, + weekly, + monthly, + all, + project_scope.as_deref(), // added: pass project scope + ); + } _ => {} // Continue with text format } let summary = tracker - .get_summary() + .get_summary_filtered(project_scope.as_deref()) // changed: use filtered variant .context("Failed to load token savings summary from database")?; if summary.total_commands == 0 { @@ -39,9 +60,18 @@ pub fn run( // Default view (summary) if !daily && !weekly && !monthly && !all { - // added: styled header with bold title - println!("{}", styled("RTK Token Savings (Global Scope)", true)); + // added: scope-aware styled header with bold title + let title = if project_scope.is_some() { + "RTK Token Savings (Project Scope)" + } else { + "RTK Token Savings (Global Scope)" + }; + println!("{}", styled(title, true)); println!("{}", "═".repeat(60)); + // added: show project path when scoped + if let Some(ref scope) = project_scope { + println!("Scope: {}", shorten_path(scope)); + } println!(); // added: KPI-style aligned output @@ -96,8 +126,19 @@ pub fn run( .unwrap_or(6) .max(6); - let table_width = - 3 + 2 + cmd_width + 2 + count_width + 2 + saved_width + 2 + 6 + 2 + time_width + 2 + impact_width; + let table_width = 3 + + 2 + + cmd_width + + 2 + + count_width + + 2 + + saved_width + + 2 + + 6 + + 2 + + time_width + + 2 + + impact_width; println!("{}", "─".repeat(table_width)); println!( "{:>3} {:count_width$} {:>saved_width$} {:>6} {:>time_width$} {: Result> { + if !project { + return Ok(None); + } + let cwd = std::env::current_dir().context("Failed to resolve current working directory")?; + let canonical = cwd.canonicalize().unwrap_or(cwd); + Ok(Some(canonical.to_string_lossy().to_string())) +} + +/// Shorten long absolute paths for display. // added +fn shorten_path(path: &str) -> String { + let path_buf = PathBuf::from(path); + let comps: Vec = path_buf + .components() + .map(|c| c.as_os_str().to_string_lossy().to_string()) + .collect(); + if comps.len() <= 4 { + return path.to_string(); + } + let root = comps[0].as_str(); + if root == "/" || root.is_empty() { + format!("/.../{}/{}", comps[comps.len() - 2], comps[comps.len() - 1]) + } else { + format!( + "{}/.../{}/{}", + root, + comps[comps.len() - 2], + comps[comps.len() - 1] + ) + } +} + fn print_ascii_graph(data: &[(String, usize)]) { if data.is_empty() { return; @@ -350,20 +424,23 @@ fn print_ascii_graph(data: &[(String, usize)]) { } } -fn print_daily_full(tracker: &Tracker) -> Result<()> { - let days = tracker.get_all_days()?; +fn print_daily_full(tracker: &Tracker, project_scope: Option<&str>) -> Result<()> { + // changed: add project scope + let days = tracker.get_all_days_filtered(project_scope)?; // changed: use filtered variant print_period_table(&days); Ok(()) } -fn print_weekly(tracker: &Tracker) -> Result<()> { - let weeks = tracker.get_by_week()?; +fn print_weekly(tracker: &Tracker, project_scope: Option<&str>) -> Result<()> { + // changed: add project scope + let weeks = tracker.get_by_week_filtered(project_scope)?; // changed: use filtered variant print_period_table(&weeks); Ok(()) } -fn print_monthly(tracker: &Tracker) -> Result<()> { - let months = tracker.get_by_month()?; +fn print_monthly(tracker: &Tracker, project_scope: Option<&str>) -> Result<()> { + // changed: add project scope + let months = tracker.get_by_month_filtered(project_scope)?; // changed: use filtered variant print_period_table(&months); Ok(()) } @@ -396,9 +473,10 @@ fn export_json( weekly: bool, monthly: bool, all: bool, + project_scope: Option<&str>, // added: project scope ) -> Result<()> { let summary = tracker - .get_summary() + .get_summary_filtered(project_scope) // changed: use filtered variant .context("Failed to load token savings summary from database")?; let export = ExportData { @@ -412,17 +490,17 @@ fn export_json( avg_time_ms: summary.avg_time_ms, }, daily: if all || daily { - Some(tracker.get_all_days()?) + Some(tracker.get_all_days_filtered(project_scope)?) // changed: use filtered } else { None }, weekly: if all || weekly { - Some(tracker.get_by_week()?) + Some(tracker.get_by_week_filtered(project_scope)?) // changed: use filtered } else { None }, monthly: if all || monthly { - Some(tracker.get_by_month()?) + Some(tracker.get_by_month_filtered(project_scope)?) // changed: use filtered } else { None }, @@ -440,9 +518,10 @@ fn export_csv( weekly: bool, monthly: bool, all: bool, + project_scope: Option<&str>, // added: project scope ) -> Result<()> { if all || daily { - let days = tracker.get_all_days()?; + let days = tracker.get_all_days_filtered(project_scope)?; // changed: use filtered println!("# Daily Data"); println!("date,commands,input_tokens,output_tokens,saved_tokens,savings_pct,total_time_ms,avg_time_ms"); for day in days { @@ -462,7 +541,7 @@ fn export_csv( } if all || weekly { - let weeks = tracker.get_by_week()?; + let weeks = tracker.get_by_week_filtered(project_scope)?; // changed: use filtered println!("# Weekly Data"); println!( "week_start,week_end,commands,input_tokens,output_tokens,saved_tokens,savings_pct,total_time_ms,avg_time_ms" @@ -485,7 +564,7 @@ fn export_csv( } if all || monthly { - let months = tracker.get_by_month()?; + let months = tracker.get_by_month_filtered(project_scope)?; // changed: use filtered println!("# Monthly Data"); println!("month,commands,input_tokens,output_tokens,saved_tokens,savings_pct,total_time_ms,avg_time_ms"); for month in months { diff --git a/src/grep_cmd.rs b/src/grep_cmd.rs index 9542a8b..afb0b7a 100644 --- a/src/grep_cmd.rs +++ b/src/grep_cmd.rs @@ -225,4 +225,22 @@ mod tests { let cleaned = clean_line(line, 15, false, "text"); assert!(!cleaned.is_empty()); } + + // Verify line numbers are always enabled in rg invocation (grep_cmd.rs:24). + // The -n/--line-numbers clap flag in main.rs is a no-op accepted for compat. + #[test] + fn test_rg_always_has_line_numbers() { + // grep_cmd::run() always passes "-n" to rg (line 24). + // This test documents that -n is built-in, so the clap flag is safe to ignore. + let mut cmd = std::process::Command::new("rg"); + cmd.args(["-n", "--no-heading", "NONEXISTENT_PATTERN_12345", "."]); + // If rg is available, it should accept -n without error (exit 1 = no match, not error) + if let Ok(output) = cmd.output() { + assert!( + output.status.code() == Some(1) || output.status.success(), + "rg -n should be accepted" + ); + } + // If rg is not installed, skip gracefully (test still passes) + } } diff --git a/src/grepai.rs b/src/grepai.rs new file mode 100644 index 0000000..eec7047 --- /dev/null +++ b/src/grepai.rs @@ -0,0 +1,344 @@ +use anyhow::{Context, Result}; +use std::io::Write; +use std::path::{Path, PathBuf}; +use std::process::{Command, Stdio}; + +const INSTALL_SCRIPT_URL: &str = + "https://raw.githubusercontent.com/yoanbernabeu/grepai/main/install.sh"; + +/// State of grepai availability for a given project +#[derive(Debug, Clone)] +pub enum GrepaiState { + /// Binary found + .grepai/config.yaml exists in project + Ready(PathBuf), + /// Binary found, but project not initialized (.grepai/config.yaml missing) + NotInitialized(PathBuf), + /// Binary not found anywhere + NotInstalled, +} + +/// Search PATH + well-known locations for the grepai binary +pub fn find_grepai_binary() -> Option { + find_grepai_binary_with_candidates( + find_grepai_binary_from_path(), + dirs::home_dir(), + PathBuf::from("/usr/local/bin/grepai"), + ) +} + +/// Detect grepai state: binary presence + project initialization +pub fn detect_grepai(project_path: &Path) -> GrepaiState { + detect_grepai_with_binary(project_path, find_grepai_binary()) +} + +fn find_grepai_binary_from_path() -> Option { + let output = Command::new("which").arg("grepai").output().ok()?; + if !output.status.success() { + return None; + } + + let path_str = String::from_utf8_lossy(&output.stdout).trim().to_string(); + if path_str.is_empty() { + return None; + } + + Some(PathBuf::from(path_str)) +} + +fn find_grepai_binary_with_candidates( + path_candidate: Option, + home_dir: Option, + global_candidate: PathBuf, +) -> Option { + if let Some(candidate) = path_candidate.filter(|p| p.exists()) { + return Some(candidate); + } + + if let Some(home) = home_dir { + let local_candidate = home.join(".local").join("bin").join("grepai"); + if local_candidate.exists() { + return Some(local_candidate); + } + } + + if global_candidate.exists() { + return Some(global_candidate); + } + + None +} + +fn detect_grepai_with_binary(project_path: &Path, binary: Option) -> GrepaiState { + match binary { + Some(binary_path) => { + let config_file = project_path.join(".grepai").join("config.yaml"); + if config_file.exists() { + GrepaiState::Ready(binary_path) + } else { + GrepaiState::NotInitialized(binary_path) + } + } + None => GrepaiState::NotInstalled, + } +} + +/// Install grepai via the official install script +/// Installs to ~/.local/bin/grepai +pub fn install_grepai(verbose: u8) -> Result { + let install_dir = dirs::home_dir() + .context("Cannot determine home directory")? + .join(".local") + .join("bin"); + + // Ensure install dir exists + std::fs::create_dir_all(&install_dir) + .with_context(|| format!("Failed to create {}", install_dir.display()))?; + + if verbose > 0 { + eprintln!("Installing grepai to {}...", install_dir.display()); + } + + // Fetch script safely (no shell interpolation) and pass to `sh` via stdin. + let script = Command::new("curl") + .args(["-fsSL", INSTALL_SCRIPT_URL]) + .output() + .context("Failed to download grepai install script (is curl available?)")?; + if !script.status.success() { + let stderr = String::from_utf8_lossy(&script.stderr); + anyhow::bail!( + "failed to download grepai install script: {}", + stderr.trim() + ); + } + + let mut installer = Command::new("sh") + .env("INSTALL_DIR", &install_dir) + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .stderr(Stdio::piped()) + .spawn() + .context("Failed to start grepai installer shell")?; + + let stdin = installer + .stdin + .as_mut() + .context("Failed to open stdin for grepai installer shell")?; + stdin + .write_all(&script.stdout) + .context("Failed to stream install script to shell")?; + + let output = installer + .wait_with_output() + .context("Failed while running grepai installer shell")?; + if !output.status.success() { + let stderr = String::from_utf8_lossy(&output.stderr); + anyhow::bail!("grepai install failed: {}", stderr.trim()); + } + + let binary_path = install_dir.join("grepai"); + if !binary_path.exists() { + anyhow::bail!( + "grepai install completed but binary not found at {}", + binary_path.display() + ); + } + + if verbose > 0 { + eprintln!("grepai installed: {}", binary_path.display()); + } + + Ok(binary_path) +} + +/// Initialize grepai in a project directory +/// Runs: grepai init --provider ollama --backend gob --yes +/// Then: grepai watch --background +pub fn init_project(binary: &Path, project_path: &Path, verbose: u8) -> Result<()> { + if verbose > 0 { + eprintln!("Initializing grepai in {}...", project_path.display()); + } + + // grepai init with defaults + let output = Command::new(binary) // use full path to avoid hook rewriting + .args(["init", "--provider", "ollama", "--backend", "gob", "--yes"]) + .current_dir(project_path) + .output() + .with_context(|| format!("Failed to run {} init", binary.display()))?; + + if !output.status.success() { + let stderr = String::from_utf8_lossy(&output.stderr); + if verbose > 0 { + eprintln!("grepai init failed: {}", stderr.trim()); + } + anyhow::bail!("grepai init failed: {}", stderr.trim()); + } + + // Start background watcher + let watch_output = Command::new(binary) + .args(["watch", "--background"]) + .current_dir(project_path) + .output() + .with_context(|| format!("Failed to run {} watch --background", binary.display()))?; + + if !watch_output.status.success() && verbose > 0 { + let stderr = String::from_utf8_lossy(&watch_output.stderr); + eprintln!("grepai watch --background warning: {}", stderr.trim()); + } + + if verbose > 0 { + eprintln!("grepai initialized in {}", project_path.display()); + } + + Ok(()) +} + +/// Execute a grepai search and return its output +/// Returns Some(output) on success, None on failure (caller falls back to built-in) +pub fn execute_search( + binary: &Path, + project_path: &Path, + query: &str, + max: usize, + json: bool, + compact: bool, +) -> Result> { + let mut cmd = Command::new(binary); // use full path to avoid hook rewriting + cmd.arg("search"); + + // Output format: --json, --compact, or --toon (default) + if json { + cmd.arg("--json"); + } else if compact { + cmd.arg("--compact"); + } else { + cmd.arg("--toon"); + } + + // Max results + cmd.args(["-n", &max.to_string()]); + + // Query (must be last) + cmd.arg(query); + + let output = cmd.current_dir(project_path).output().with_context(|| { + format!( + "Failed to execute {} search in {}", + binary.display(), + project_path.display() + ) + })?; + + if !output.status.success() { + return Ok(None); + } + + let stdout = String::from_utf8_lossy(&output.stdout).to_string(); + if stdout.trim().is_empty() { + return Ok(None); + } + + Ok(Some(stdout)) +} + +#[cfg(test)] +mod tests { + use super::*; + use tempfile::TempDir; + + fn touch(path: &Path) { + std::fs::write(path, "#!/bin/sh\necho ok\n").unwrap(); + } + + #[test] + fn detect_grepai_ready_when_config_exists() { + let dir = TempDir::new().unwrap(); + let grepai_dir = dir.path().join(".grepai"); + std::fs::create_dir_all(&grepai_dir).unwrap(); + std::fs::write(grepai_dir.join("config.yaml"), "provider: ollama").unwrap(); + + let fake_binary = dir.path().join("grepai"); + touch(&fake_binary); + + let state = detect_grepai_with_binary(dir.path(), Some(fake_binary.clone())); + match state { + GrepaiState::Ready(path) => assert_eq!(path, fake_binary), + other => panic!("expected Ready, got {other:?}"), + } + } + + #[test] + fn detect_grepai_not_initialized_when_config_missing() { + let dir = TempDir::new().unwrap(); + let fake_binary = dir.path().join("grepai"); + touch(&fake_binary); + + let state = detect_grepai_with_binary(dir.path(), Some(fake_binary.clone())); + match state { + GrepaiState::NotInitialized(path) => assert_eq!(path, fake_binary), + other => panic!("expected NotInitialized, got {other:?}"), + } + } + + #[test] + fn detect_grepai_not_installed_returns_not_installed() { + let dir = TempDir::new().unwrap(); + assert!(matches!( + detect_grepai_with_binary(dir.path(), None), + GrepaiState::NotInstalled + )); + } + + #[test] + fn find_grepai_binary_prefers_path_candidate() { + let dir = TempDir::new().unwrap(); + let path_candidate = dir.path().join("path-grepai"); + let home = dir.path().join("home"); + let global = dir.path().join("global-grepai"); + std::fs::create_dir_all(home.join(".local/bin")).unwrap(); + touch(&path_candidate); + touch(&home.join(".local/bin/grepai")); + touch(&global); + + let found = + find_grepai_binary_with_candidates(Some(path_candidate.clone()), Some(home), global); + assert_eq!(found, Some(path_candidate)); + } + + #[test] + fn find_grepai_binary_falls_back_to_home_then_global() { + let dir = TempDir::new().unwrap(); + let home = dir.path().join("home"); + let global = dir.path().join("global-grepai"); + let local = home.join(".local/bin/grepai"); + std::fs::create_dir_all(home.join(".local/bin")).unwrap(); + touch(&local); + touch(&global); + + let from_home = find_grepai_binary_with_candidates( + Some(dir.path().join("missing-path-grepai")), + Some(home.clone()), + global.clone(), + ); + assert_eq!(from_home, Some(local)); + + std::fs::remove_file(home.join(".local/bin/grepai")).unwrap(); + let from_global = + find_grepai_binary_with_candidates(None, Some(home.clone()), global.clone()); + assert_eq!(from_global, Some(global)); + } + + #[test] + fn find_grepai_binary_returns_none_when_no_candidates_exist() { + let dir = TempDir::new().unwrap(); + let home = dir.path().join("home"); + std::fs::create_dir_all(home.join(".local/bin")).unwrap(); + let missing_global = dir.path().join("missing-global-grepai"); + + let found = find_grepai_binary_with_candidates( + Some(dir.path().join("missing-path-grepai")), + Some(home), + missing_global, + ); + assert_eq!(found, None); + } +} diff --git a/src/init.rs b/src/init.rs index 961e4ac..e090535 100644 --- a/src/init.rs +++ b/src/init.rs @@ -1,3 +1,4 @@ +use crate::grepai; // grepai integration use anyhow::{Context, Result}; use std::fs; use std::io::Write; @@ -44,6 +45,14 @@ git add . && git commit -m "msg" && git push rtk git add . && rtk git commit -m "msg" && rtk git push ``` +## Search Priority Policy + +**Search priority (mandatory): rgai > rg > grep.** + +- Use `rtk rgai` first for semantic/intention-based discovery. +- Use `rtk grep` for exact/regex matching. +- `rtk grep` internally follows `rg -> grep` backend fallback automatically. + ## RTK Commands by Workflow ### Build & Compile (80-90% savings) @@ -102,11 +111,12 @@ rtk npx # Compact npx command output rtk prisma # Prisma without ASCII art (88%) ``` -### Files & Search (60-75% savings) +### Files & Search (60-85% savings) ```bash rtk ls # Tree format, compact (65%) rtk read # Code reading with filtering (60%) -rtk grep # Search grouped by file (75%) +rtk rgai # Semantic search ranked by relevance (85%) +rtk grep # Exact/regex search (internal rg -> grep fallback) rtk find # Find grouped by directory (70%) ``` @@ -155,7 +165,7 @@ rtk init --global # Add RTK to ~/.claude/CLAUDE.md | Git | status, log, diff, add, commit | 59-80% | | GitHub | gh pr, gh run, gh issue | 26-87% | | Package Managers | pnpm, npm, npx | 70-90% | -| Files | ls, read, grep, find | 60-75% | +| Files | ls, read, grep, rgai, find | 60-85% | | Infrastructure | docker, kubectl | 85% | | Network | curl, wget | 65-70% | @@ -696,11 +706,96 @@ fn run_default_mode(global: bool, patch_mode: PatchMode, verbose: u8) -> Result< } } + // 6. Offer grepai installation + setup_grepai(patch_mode, verbose)?; + println!(); // Final newline Ok(()) } +/// Offer grepai installation during `rtk init --global` +fn setup_grepai(patch_mode: PatchMode, verbose: u8) -> Result<()> { + // Check if grepai is already installed + if let Some(path) = grepai::find_grepai_binary() { + println!("\n grepai: already installed at {}", path.display()); + return Ok(()); + } + + // Not installed — decide based on patch_mode + match patch_mode { + PatchMode::Auto => { + // Install without prompting + println!("\n Installing grepai..."); + match grepai::install_grepai(verbose) { + Ok(path) => { + println!(" grepai installed: {}", path.display()); + println!( + " Run `grepai init` in any project, then `grepai watch --background`." + ); + } + Err(e) => { + eprintln!(" grepai install failed: {}", e); + eprintln!(" Install manually: https://github.com/yoanbernabeu/grepai"); + } + } + } + PatchMode::Skip => { + // Print manual instructions only + println!("\n grepai: not installed (skipped)"); + println!(" Install manually: https://github.com/yoanbernabeu/grepai"); + } + PatchMode::Ask => { + // Prompt with Y as default (capital Y, unlike settings.json which defaults to N) + if prompt_grepai_consent()? { + println!(" Installing grepai..."); + match grepai::install_grepai(verbose) { + Ok(path) => { + println!(" grepai installed: {}", path.display()); + println!( + " Run `grepai init` in any project, then `grepai watch --background`." + ); + } + Err(e) => { + eprintln!(" grepai install failed: {}", e); + eprintln!(" Install manually: https://github.com/yoanbernabeu/grepai"); + } + } + } else { + println!(" grepai: skipped"); + println!(" Install later: https://github.com/yoanbernabeu/grepai"); + } + } + } + + Ok(()) +} + +/// Prompt user for consent to install grepai +/// Default is Yes (capital Y) — unlike settings.json patch which defaults to No +fn prompt_grepai_consent() -> Result { + use std::io::{self, BufRead, IsTerminal}; + + eprintln!("\nInstall grepai for semantic code search? [Y/n] "); + + // If stdin is not a terminal (piped), default to Yes + if !io::stdin().is_terminal() { + eprintln!("(non-interactive mode, defaulting to Y)"); + return Ok(true); + } + + let stdin = io::stdin(); + let mut line = String::new(); + stdin + .lock() + .read_line(&mut line) + .context("Failed to read user input")?; + + let response = line.trim().to_lowercase(); + // Default is Yes: empty input or explicit y/yes + Ok(response.is_empty() || response == "y" || response == "yes") +} + /// Hook-only mode: just the hook, no RTK.md #[cfg(not(unix))] fn run_hook_only_mode(_global: bool, _patch_mode: PatchMode, _verbose: u8) -> Result<()> { @@ -1081,7 +1176,11 @@ pub fn show_config() -> Result<()> { println!("⚪ settings.json: not found"); } - println!("\nUsage:"); + println!("\nSearch priority (mandatory): rgai > rg > grep."); + println!( + " Use rtk rgai first; use rtk grep for exact/regex (internal rg -> grep fallback).\n" + ); + println!("Usage:"); println!(" rtk init # Full injection into local CLAUDE.md"); println!(" rtk init -g # Hook + RTK.md + @RTK.md + settings.json (recommended)"); println!(" rtk init -g --auto-patch # Same as above but no prompt"); @@ -1116,6 +1215,7 @@ mod tests { "rtk git", "rtk docker", "rtk kubectl", + "rtk rgai", ] { assert!( RTK_INSTRUCTIONS.contains(cmd), @@ -1195,6 +1295,7 @@ More content"#; // Just verify RTK_INSTRUCTIONS constant has the right content assert!(RTK_INSTRUCTIONS.contains("")); assert!(RTK_INSTRUCTIONS.len() > 4000); } @@ -1248,6 +1349,33 @@ More notes assert_eq!(content, input); } + #[test] + fn test_search_priority_policy_in_init_and_slim_templates() { + let policy = "Search priority (mandatory): rgai > rg > grep."; + assert!( + RTK_INSTRUCTIONS.contains(policy), + "RTK_INSTRUCTIONS must include strict search priority policy" + ); + assert!( + RTK_SLIM.contains(policy), + "RTK_SLIM must include strict search priority policy" + ); + } + + #[test] + fn test_files_search_examples_prioritize_rgai_before_grep() { + let rgai_pos = RTK_INSTRUCTIONS + .find("rtk rgai ") + .expect("rtk rgai example missing"); + let grep_pos = RTK_INSTRUCTIONS + .find("rtk grep ") + .expect("rtk grep example missing"); + assert!( + rgai_pos < grep_pos, + "Files/Search examples must prioritize rtk rgai before rtk grep" + ); + } + #[test] fn test_init_is_idempotent() { let temp = TempDir::new().unwrap(); diff --git a/src/main.rs b/src/main.rs index cef7f3e..ca6a819 100644 --- a/src/main.rs +++ b/src/main.rs @@ -18,6 +18,7 @@ mod git; mod go_cmd; mod golangci_cmd; mod grep_cmd; +mod grepai; // grepai external semantic search integration mod init; mod json_cmd; mod learn; @@ -35,6 +36,7 @@ mod prettier_cmd; mod prisma_cmd; mod pytest_cmd; mod read; +mod rgai_cmd; // semantic search command (grepai-style intent matching) mod ruff_cmd; mod runner; mod summary; @@ -245,11 +247,45 @@ enum Commands { /// Filter by file type (e.g., ts, py, rust) #[arg(short = 't', long)] file_type: Option, + /// Show line numbers (always on, accepted for grep/rg compatibility) + #[arg(short = 'n', long)] + line_numbers: bool, /// Extra ripgrep arguments (e.g., -i, -A 3, -w, --glob) #[arg(trailing_var_arg = true, allow_hyphen_values = true)] extra_args: Vec, }, + /// Rust-native semantic search (grepai-style intent matching) + Rgai { + /// Natural-language query + #[arg(required = true, num_args = 1..)] + query: Vec, + /// Path to search in + #[arg(short, long, default_value = ".")] + path: String, + /// Max files to show + #[arg(short, long, default_value = "8")] + max: usize, + /// Context lines around each match + #[arg(short = 'c', long, default_value = "1")] + context: usize, + /// Filter by file type (e.g., ts, py, rust) + #[arg(short = 't', long)] + file_type: Option, + /// Skip files larger than N KB + #[arg(long, default_value = "512")] + max_file_kb: usize, + /// Output machine-readable JSON + #[arg(long)] + json: bool, + /// Compact output (fewer lines per hit) + #[arg(long)] + compact: bool, + /// Force built-in keyword search (skip grepai delegation) + #[arg(long)] + builtin: bool, + }, + /// Initialize rtk instructions in CLAUDE.md Init { /// Add to global ~/.claude/CLAUDE.md instead of local @@ -295,6 +331,9 @@ enum Commands { /// Show token savings summary and history Gain { + /// Filter statistics to current project (current working directory) // added + #[arg(short, long)] + project: bool, /// Show ASCII graph of daily savings #[arg(short, long)] graph: bool, @@ -1028,6 +1067,7 @@ fn main() -> Result<()> { max, context_only, file_type, + line_numbers: _, // no-op: line numbers always enabled in grep_cmd::run extra_args, } => { grep_cmd::run( @@ -1042,6 +1082,33 @@ fn main() -> Result<()> { )?; } + Commands::Rgai { + query, + path, + max, + context, + file_type, + max_file_kb, + json, + compact, + builtin, // --builtin flag: skip grepai delegation + } => { + // Backward-compat: rtk rgai "query words" ./src -> path="./src" + let (query, path) = normalize_rgai_args(query, path); + rgai_cmd::run( + &query, + &path, + max, + context, + file_type.as_deref(), + max_file_kb, + json, + compact, + builtin, // pass --builtin flag + cli.verbose, + )?; + } + Commands::Init { global, show, @@ -1076,6 +1143,7 @@ fn main() -> Result<()> { } Commands::Gain { + project, // added graph, history, quota, @@ -1087,6 +1155,7 @@ fn main() -> Result<()> { format, } => { gain::run( + project, // added: pass project flag graph, history, quota, @@ -1409,3 +1478,91 @@ fn main() -> Result<()> { Ok(()) } + +/// Normalize rgai positional args: detect trailing path token in query words. +fn normalize_rgai_args(mut query_parts: Vec, mut path: String) -> (String, String) { + if path == "." && query_parts.len() > 1 { + if let Some(last) = query_parts.last().cloned() { + if looks_like_path_token(&last) { + path = last; + query_parts.pop(); + } + } + } + let query = query_parts.join(" "); + (query, path) +} + +fn looks_like_path_token(token: &str) -> bool { + // FIX: removed bare contains('/') — too greedy, treats "client/server" as a path. + // Now only matches tokens that look like actual filesystem paths. + token == "." + || token == ".." + || token.starts_with("./") + || token.starts_with("../") + || token.starts_with('/') + || token.starts_with("~/") +} + +#[cfg(test)] +mod rgai_arg_tests { + use super::*; + + #[test] + fn normalize_rgai_keeps_multiword_query() { + let (query, path) = normalize_rgai_args( + vec!["token".to_string(), "refresh".to_string()], + ".".to_string(), + ); + assert_eq!(query, "token refresh"); + assert_eq!(path, "."); + } + + #[test] + fn normalize_rgai_supports_old_positional_path() { + let (query, path) = normalize_rgai_args( + vec!["auth".to_string(), "flow".to_string(), "./src".to_string()], + ".".to_string(), + ); + assert_eq!(query, "auth flow"); + assert_eq!(path, "./src"); + } + + #[test] + fn normalize_rgai_does_not_treat_plain_word_as_path() { + let (query, path) = normalize_rgai_args( + vec!["domain".to_string(), "model".to_string()], + ".".to_string(), + ); + assert_eq!(query, "domain model"); + assert_eq!(path, "."); + } + + // FIX: slash-containing words like "client/server" must NOT be treated as paths + #[test] + fn normalize_rgai_does_not_treat_slash_word_as_path() { + let (query, path) = normalize_rgai_args( + vec!["client/server".to_string(), "architecture".to_string()], + ".".to_string(), + ); + assert_eq!(query, "client/server architecture"); + assert_eq!(path, "."); + } + + #[test] + fn looks_like_path_recognizes_real_paths() { + assert!(looks_like_path_token("./src")); + assert!(looks_like_path_token("../lib")); + assert!(looks_like_path_token("/usr/local")); + assert!(looks_like_path_token("~/projects")); + assert!(looks_like_path_token(".")); + assert!(looks_like_path_token("..")); + } + + #[test] + fn looks_like_path_rejects_non_paths() { + assert!(!looks_like_path_token("client/server")); + assert!(!looks_like_path_token("input/output")); + assert!(!looks_like_path_token("read/write")); + } +} diff --git a/src/rgai_cmd.rs b/src/rgai_cmd.rs new file mode 100644 index 0000000..8c18654 --- /dev/null +++ b/src/rgai_cmd.rs @@ -0,0 +1,1022 @@ +use crate::config; // grepai config +use crate::grepai; // grepai delegation +use crate::tracking; +use anyhow::{bail, Result}; +use ignore::WalkBuilder; +use lazy_static::lazy_static; +use regex::Regex; +use serde_json::json; +use std::collections::HashSet; +use std::fs; +use std::path::{Path, PathBuf}; + +const MAX_SNIPPETS_PER_FILE: usize = 2; +const MAX_SNIPPET_LINE_LEN: usize = 140; +const MIN_FILE_SCORE: f64 = 2.4; + +const STOP_WORDS: &[&str] = &[ + "a", "an", "and", "are", "as", "at", "be", "by", "code", "file", "find", "for", "from", "how", + "in", "is", "it", "of", "on", "or", "search", "show", "that", "the", "this", "to", "use", + "using", "what", "when", "where", "with", "why", +]; + +lazy_static! { + static ref SYMBOL_DEF_RE: Regex = Regex::new( + r"^\s*(?:pub\s+)?(?:async\s+)?(?:fn|def|class|struct|enum|trait|interface|impl|type)\s+[A-Za-z_][A-Za-z0-9_]*" + ) + .expect("valid symbol regex"); +} + +#[derive(Debug, Clone)] +struct QueryModel { + phrase: String, + terms: Vec, +} + +#[derive(Debug, Clone)] +struct LineCandidate { + line_idx: usize, + score: f64, + matched_terms: Vec, +} + +#[derive(Debug, Clone)] +struct Snippet { + lines: Vec<(usize, String)>, + matched_terms: Vec, +} + +#[derive(Debug, Clone)] +struct SearchHit { + path: String, + score: f64, + matched_lines: usize, + snippets: Vec, +} + +#[derive(Debug, Default)] +struct SearchOutcome { + scanned_files: usize, + skipped_large: usize, + skipped_binary: usize, + hits: Vec, + raw_output: String, +} + +pub fn run( + query: &str, + path: &str, + max_results: usize, + context_lines: usize, + file_type: Option<&str>, + max_file_kb: usize, + json_output: bool, + compact: bool, + builtin: bool, // --builtin flag: skip grepai delegation + verbose: u8, +) -> Result<()> { + let timer = tracking::TimedExecution::start(); + + let query = query.trim(); + if query.is_empty() { + bail!("query cannot be empty"); + } + + let root = Path::new(path); + if !root.exists() { + bail!("path does not exist: {}", path); + } + + // Try grepai delegation first (unless --builtin flag is set) + if !builtin { + if let Some(output) = + try_grepai_delegation(query, root, max_results, json_output, compact, verbose)? + { + print!("{}", output); + timer.track( + &format!("grepai search '{}' {}", query, path), + "rtk rgai (grepai)", + &output, + &output, + ); + return Ok(()); + } + // Fall through to built-in search + } + + let query_model = build_query_model(query); + if verbose > 0 { + eprintln!( + "rgai: '{}' in {} (terms: {})", + query, + path, + query_model.terms.join(", ") + ); + } + + let max_file_bytes = max_file_kb.saturating_mul(1024).max(1024); + let effective_context = if compact { 0 } else { context_lines }; + let snippets_per_file = if compact { 1 } else { MAX_SNIPPETS_PER_FILE }; + let outcome = search_project( + &query_model, + root, + effective_context, + snippets_per_file, + file_type, + max_file_bytes, + verbose, + )?; + + let mut rendered = String::new(); + if outcome.hits.is_empty() { + if json_output { + rendered = serde_json::to_string_pretty(&json!({ + "query": query, + "path": path, + "total_hits": 0, + "scanned_files": outcome.scanned_files, + "skipped_large": outcome.skipped_large, + "skipped_binary": outcome.skipped_binary, + "hits": [] + }))?; + rendered.push('\n'); + } else { + rendered.push_str(&format!("🧠 0 for '{}'\n", query)); + } + print!("{}", rendered); + timer.track( + &format!("grepai search '{}' {}", query, path), + "rtk rgai", + &outcome.raw_output, + &rendered, + ); + return Ok(()); + } + + if json_output { + let hits_json: Vec<_> = outcome + .hits + .iter() + .take(max_results) + .map(|hit| { + let snippets: Vec<_> = hit + .snippets + .iter() + .map(|snippet| { + let lines: Vec<_> = snippet + .lines + .iter() + .map(|(line_no, text)| json!({ "line": line_no, "text": text })) + .collect(); + json!({ + "lines": lines, + "matched_terms": snippet.matched_terms, + }) + }) + .collect(); + json!({ + "path": hit.path, + "score": hit.score, + "matched_lines": hit.matched_lines, + "snippets": snippets, + }) + }) + .collect(); + + rendered = serde_json::to_string_pretty(&json!({ + "query": query, + "path": path, + "total_hits": outcome.hits.len(), + "shown_hits": max_results.min(outcome.hits.len()), + "scanned_files": outcome.scanned_files, + "skipped_large": outcome.skipped_large, + "skipped_binary": outcome.skipped_binary, + "hits": hits_json + }))?; + rendered.push('\n'); + print!("{}", rendered); + timer.track( + &format!("grepai search '{}' {}", query, path), + "rtk rgai", + &outcome.raw_output, + &rendered, + ); + return Ok(()); + } + + rendered.push_str(&format!( + "🧠 {}F for '{}' (scan {}F)\n", + outcome.hits.len(), + query, + outcome.scanned_files + )); + rendered.push('\n'); + + for hit in outcome.hits.iter().take(max_results) { + rendered.push_str(&format!( + "📄 {} [{:.1}]\n", + compact_path(&hit.path), + hit.score + )); + + for snippet in &hit.snippets { + for (line_no, line) in &snippet.lines { + rendered.push_str(&format!(" {:>4}: {}\n", line_no, line)); + } + + if !compact && !snippet.matched_terms.is_empty() { + rendered.push_str(&format!(" ~ {}\n", snippet.matched_terms.join(", "))); + } + rendered.push('\n'); + } + + let shown_lines = hit.snippets.len(); + if hit.matched_lines > shown_lines { + rendered.push_str(&format!( + " +{} more lines\n\n", + hit.matched_lines - shown_lines + )); + } + } + + if outcome.hits.len() > max_results { + rendered.push_str(&format!("... +{}F\n", outcome.hits.len() - max_results)); + } + + if verbose > 0 { + rendered.push_str(&format!( + "\nscan stats: skipped {} large, {} binary\n", + outcome.skipped_large, outcome.skipped_binary + )); + } + + print!("{}", rendered); + timer.track( + &format!("grepai search '{}' {}", query, path), + "rtk rgai", + &outcome.raw_output, + &rendered, + ); + + Ok(()) +} + +/// Try to delegate search to external grepai binary +/// Returns Some(output) if grepai handled the search, None to fall back to built-in +fn try_grepai_delegation( + query: &str, + project_path: &Path, + max: usize, + json: bool, + compact: bool, + verbose: u8, +) -> Result> { + let project_dir = resolve_grepai_project_dir(project_path); + + // Check config: is grepai delegation enabled? + let cfg = config::Config::load().unwrap_or_default(); + if !cfg.grepai.enabled { + if verbose > 0 { + eprintln!("rgai: grepai delegation disabled in config"); + } + return Ok(None); + } + + // Use custom binary path from config, or auto-detect + let state = if let Some(ref custom_path) = cfg.grepai.binary_path { + if custom_path.exists() { + let config_file = project_dir.join(".grepai").join("config.yaml"); + if config_file.exists() { + grepai::GrepaiState::Ready(custom_path.clone()) + } else { + grepai::GrepaiState::NotInitialized(custom_path.clone()) + } + } else { + if verbose > 0 { + eprintln!( + "rgai: configured binary not found: {}", + custom_path.display() + ); + } + return Ok(None); + } + } else { + grepai::detect_grepai(project_dir) + }; + + match state { + grepai::GrepaiState::Ready(binary) => { + if verbose > 0 { + eprintln!("rgai: delegating to grepai ({})", binary.display()); + } + match grepai::execute_search(&binary, project_dir, query, max, json, compact) { + Ok(output) => Ok(output), + Err(e) => { + if verbose > 0 { + eprintln!( + "rgai: grepai search failed: {}, falling back to built-in", + e + ); + } + Ok(None) + } + } + } + grepai::GrepaiState::NotInitialized(binary) => { + if cfg.grepai.auto_init { + if verbose > 0 { + eprintln!("rgai: auto-initializing grepai in project..."); + } + match grepai::init_project(&binary, project_dir, verbose) { + Ok(()) => { + match grepai::execute_search( + &binary, + project_dir, + query, + max, + json, + compact, + ) { + Ok(output) => Ok(output), + Err(e) => { + if verbose > 0 { + eprintln!( + "rgai: grepai search failed after init: {}, falling back", + e + ); + } + Ok(None) + } + } + } + Err(e) => { + if verbose > 0 { + eprintln!( + "rgai: grepai auto-init failed: {}, falling back to built-in", + e + ); + } + Ok(None) + } + } + } else { + if verbose > 0 { + eprintln!("rgai: grepai not initialized, auto_init disabled, using built-in"); + } + Ok(None) + } + } + grepai::GrepaiState::NotInstalled => { + // Silent: no nagging — install happens via `rtk init` + Ok(None) + } + } +} + +fn resolve_grepai_project_dir(project_path: &Path) -> &Path { + if project_path.is_dir() { + project_path + } else { + project_path.parent().unwrap_or(project_path) + } +} + +fn search_project( + query: &QueryModel, + root: &Path, + context_lines: usize, + snippets_per_file: usize, + file_type: Option<&str>, + max_file_bytes: usize, + _verbose: u8, +) -> Result { + let mut outcome = SearchOutcome::default(); + + let walker = WalkBuilder::new(root) + .hidden(true) + .git_ignore(true) + .git_global(true) + .git_exclude(true) + .build(); + + for entry in walker { + let entry = match entry { + Ok(e) => e, + Err(_) => continue, + }; + + if !entry + .file_type() + .as_ref() + .map(|ft| ft.is_file()) + .unwrap_or(false) + { + continue; + } + + let full_path = entry.path(); + if !is_supported_text_file(full_path) { + continue; + } + + if let Some(ft) = file_type { + if !matches_file_type(full_path, ft) { + continue; + } + } + + let metadata = match fs::metadata(full_path) { + Ok(m) => m, + Err(_) => continue, + }; + outcome.scanned_files += 1; + + if metadata.len() > max_file_bytes as u64 { + outcome.skipped_large += 1; + continue; + } + + let bytes = match fs::read(full_path) { + Ok(b) => b, + Err(_) => continue, + }; + + if looks_binary(&bytes) { + outcome.skipped_binary += 1; + continue; + } + + let content = String::from_utf8_lossy(&bytes).to_string(); + let display_path = compact_display_path(full_path, root); + if let Some(hit) = analyze_file( + &display_path, + &content, + query, + context_lines, + snippets_per_file, + ) { + outcome.hits.push(hit); + } + } + + outcome.hits.sort_by(|a, b| { + b.score + .total_cmp(&a.score) + .then_with(|| a.path.to_lowercase().cmp(&b.path.to_lowercase())) + }); + + outcome.raw_output = build_raw_output(&outcome.hits); + Ok(outcome) +} + +fn analyze_file( + path: &str, + content: &str, + query: &QueryModel, + context_lines: usize, + snippets_per_file: usize, +) -> Option { + // FIX: extract extension for extension-aware comment detection + let ext = Path::new(path) + .extension() + .and_then(|e| e.to_str()) + .unwrap_or(""); + let mut candidates = Vec::new(); + for (idx, line) in content.lines().enumerate() { + if let Some(candidate) = score_line(idx, line, query, ext) { + candidates.push(candidate); + } + } + + let path_score = score_path(path, query); + if candidates.is_empty() && path_score < MIN_FILE_SCORE { + return None; + } + + candidates.sort_by(|a, b| { + b.score + .total_cmp(&a.score) + .then_with(|| a.line_idx.cmp(&b.line_idx)) + }); + + let mut selected = Vec::new(); + let overlap_window = (context_lines * 2 + 1) as isize; + for cand in candidates.iter().cloned() { + let overlaps = selected.iter().any(|existing: &LineCandidate| { + let delta = existing.line_idx as isize - cand.line_idx as isize; + delta.abs() <= overlap_window + }); + if overlaps { + continue; + } + selected.push(cand); + if selected.len() >= snippets_per_file { + break; + } + } + + if selected.is_empty() { + return None; + } + + let lines: Vec<&str> = content.lines().collect(); + let mut snippets = Vec::new(); + for cand in &selected { + snippets.push(build_snippet(&lines, cand, context_lines)); + } + + let mut file_score = path_score + (candidates.len() as f64).ln_1p(); + for (idx, cand) in selected.iter().enumerate() { + let weight = match idx { + 0 => 1.0, + 1 => 0.45, + _ => 0.25, + }; + file_score += cand.score * weight; + } + + if file_score < MIN_FILE_SCORE { + return None; + } + + Some(SearchHit { + path: path.to_string(), + score: file_score, + matched_lines: candidates.len(), + snippets, + }) +} + +fn build_snippet(lines: &[&str], candidate: &LineCandidate, context_lines: usize) -> Snippet { + if lines.is_empty() { + return Snippet { + lines: vec![(candidate.line_idx + 1, String::new())], + matched_terms: candidate.matched_terms.clone(), + }; + } + + let start = candidate.line_idx.saturating_sub(context_lines); + let end = (candidate.line_idx + context_lines + 1).min(lines.len()); + let mut rendered_lines = Vec::new(); + + for (idx, line) in lines.iter().enumerate().take(end).skip(start) { + let cleaned = line.trim(); + if cleaned.is_empty() { + continue; + } + rendered_lines.push((idx + 1, truncate_chars(cleaned, MAX_SNIPPET_LINE_LEN))); + } + + if rendered_lines.is_empty() { + rendered_lines.push((candidate.line_idx + 1, String::new())); + } + + Snippet { + lines: rendered_lines, + matched_terms: candidate.matched_terms.clone(), + } +} + +fn build_raw_output(hits: &[SearchHit]) -> String { + let mut raw = String::new(); + for hit in hits.iter().take(60) { + for snippet in &hit.snippets { + for (line_no, line) in &snippet.lines { + raw.push_str(&format!("{}:{}:{}\n", hit.path, line_no, line)); + } + } + } + raw +} + +fn score_line(line_idx: usize, line: &str, query: &QueryModel, ext: &str) -> Option { + let trimmed = line.trim(); + if trimmed.is_empty() { + return None; + } + + let lower = trimmed.to_lowercase(); + let mut score = 0.0; + let mut matched_terms = Vec::new(); + + if query.phrase.len() >= 3 && lower.contains(&query.phrase) { + score += 6.0; + } + + for term in &query.terms { + if lower.contains(term) { + score += if term.len() >= 5 { 1.7 } else { 1.4 }; + matched_terms.push(term.clone()); + } + } + + let unique_matches = dedup_terms(matched_terms); + if unique_matches.is_empty() { + return None; + } + + if unique_matches.len() > 1 { + score += 1.2; + } + + if is_symbol_definition(trimmed) { + score += 2.5; + } + + if is_comment_line(trimmed, ext) { + // FIX: pass ext for extension-aware comment detection + score *= 0.7; + } + + if trimmed.chars().count() > 220 { + score *= 0.9; + } + + if score < 1.2 { + return None; + } + + Some(LineCandidate { + line_idx, + score, + matched_terms: unique_matches, + }) +} + +fn score_path(path: &str, query: &QueryModel) -> f64 { + let lower = path.to_lowercase(); + let mut score = 0.0; + + if query.phrase.len() >= 3 && lower.contains(&query.phrase) { + score += 3.5; + } + + for term in &query.terms { + if lower.contains(term) { + score += 1.2; + } + } + + score +} + +fn build_query_model(query: &str) -> QueryModel { + let phrase = query.trim().to_lowercase(); + let mut terms = Vec::new(); + let mut seen = HashSet::new(); + + for token in split_terms(&phrase) { + if token.len() < 2 || STOP_WORDS.contains(&token.as_str()) { + continue; + } + push_unique(&mut terms, &mut seen, &token); + + let stemmed = stem_token(&token); + if stemmed != token && stemmed.len() >= 2 { + push_unique(&mut terms, &mut seen, &stemmed); + } + } + + if terms.is_empty() && !phrase.is_empty() { + terms.push(phrase.clone()); + } + + QueryModel { phrase, terms } +} + +fn split_terms(input: &str) -> Vec { + let mut tokens = Vec::new(); + let mut current = String::new(); + + for ch in input.chars() { + if ch.is_alphanumeric() || ch == '_' { + current.extend(ch.to_lowercase()); + } else if !current.is_empty() { + tokens.push(std::mem::take(&mut current)); + } + } + + if !current.is_empty() { + tokens.push(current); + } + + tokens +} + +fn stem_token(token: &str) -> String { + if !token.is_ascii() { + return token.to_string(); + } + + // FIX: removed "es" suffix — it broke stems for -ce/-ge/-ve words common in code + // (caches→cach, services→servic, changes→chang). Stripping just "s" handles + // these correctly (caches→cache, services→service). The trade-off (classes→classe) + // is acceptable since original unstemmed tokens are also kept in the query model. + let suffixes = ["ingly", "edly", "ing", "ed", "s"]; + for suffix in suffixes { + if token.len() > suffix.len() + 2 && token.ends_with(suffix) { + return token[..token.len() - suffix.len()].to_string(); + } + } + token.to_string() +} + +fn push_unique(out: &mut Vec, seen: &mut HashSet, item: &str) { + if seen.insert(item.to_string()) { + out.push(item.to_string()); + } +} + +fn dedup_terms(input: Vec) -> Vec { + let mut out = Vec::new(); + let mut seen = HashSet::new(); + for item in input { + if seen.insert(item.clone()) { + out.push(item); + } + } + out +} + +fn is_symbol_definition(line: &str) -> bool { + SYMBOL_DEF_RE.is_match(line) +} + +// FIX: accept file extension to avoid penalizing Markdown headers and YAML keys. +// '#' is only treated as a comment prefix for scripting languages (py, sh, rb, etc.). +fn is_comment_line(line: &str, ext: &str) -> bool { + let trimmed = line.trim_start(); + if trimmed.starts_with("//") + || trimmed.starts_with('*') + || trimmed.starts_with("/*") + || trimmed.starts_with("--") + { + return true; + } + // Only treat '#' as comment for languages that actually use it + if trimmed.starts_with('#') { + return matches!( + ext, + "py" | "sh" + | "bash" + | "zsh" + | "rb" + | "pl" + | "pm" + | "r" + | "jl" + | "makefile" + | "mk" + | "dockerfile" + | "tf" + | "cfg" + | "conf" + | "ini" + ); + } + false +} + +fn looks_binary(bytes: &[u8]) -> bool { + bytes.iter().take(4096).any(|b| *b == 0) +} + +fn is_supported_text_file(path: &Path) -> bool { + let ext = path + .extension() + .and_then(|e| e.to_str()) + .map(|e| e.to_ascii_lowercase()) + .unwrap_or_default(); + + !matches!( + ext.as_str(), + "png" + | "jpg" + | "jpeg" + | "gif" + | "webp" + | "ico" + | "pdf" + | "zip" + | "gz" + | "tar" + | "7z" + | "mp3" + | "mp4" + | "mov" + | "db" + | "sqlite" + | "woff" + | "woff2" + | "ttf" + | "otf" + | "lock" + | "jar" + | "class" + | "wasm" + ) +} + +fn matches_file_type(path: &Path, file_type: &str) -> bool { + let wanted = file_type.trim_start_matches('.').to_ascii_lowercase(); + if wanted.is_empty() { + return true; + } + + let ext = path + .extension() + .and_then(|e| e.to_str()) + .map(|e| e.to_ascii_lowercase()) + .unwrap_or_default(); + + match wanted.as_str() { + "rust" | "rs" => ext == "rs", + "python" | "py" => ext == "py", + "javascript" | "js" => matches!(ext.as_str(), "js" | "jsx" | "mjs" | "cjs"), + "typescript" | "ts" => matches!(ext.as_str(), "ts" | "tsx"), + "go" => ext == "go", + "java" => ext == "java", + "c" => matches!(ext.as_str(), "c" | "h"), + "cpp" | "c++" => matches!(ext.as_str(), "cc" | "cpp" | "cxx" | "hpp" | "hh" | "hxx"), + "markdown" | "md" => matches!(ext.as_str(), "md" | "mdx"), + "json" => ext == "json", + other => ext == other, + } +} + +fn compact_display_path(path: &Path, root: &Path) -> String { + let rel = match path.strip_prefix(root) { + Ok(r) => r.to_path_buf(), + Err(_) => { + if let Ok(cwd) = std::env::current_dir() { + match path.strip_prefix(cwd) { + Ok(r) => r.to_path_buf(), + Err(_) => PathBuf::from(path), + } + } else { + PathBuf::from(path) + } + } + }; + rel.to_string_lossy().trim_start_matches("./").to_string() +} + +fn compact_path(path: &str) -> String { + if path.len() <= 58 { + return path.to_string(); + } + + let parts: Vec<&str> = path.split('/').collect(); + if parts.len() <= 3 { + return path.to_string(); + } + + format!( + "{}/.../{}/{}", + parts[0], + parts[parts.len() - 2], + parts[parts.len() - 1] + ) +} + +fn truncate_chars(input: &str, max_len: usize) -> String { + if input.chars().count() <= max_len { + return input.to_string(); + } + if max_len <= 3 { + return "...".to_string(); + } + let clipped: String = input.chars().take(max_len - 3).collect(); + format!("{clipped}...") +} + +#[cfg(test)] +mod tests { + use super::*; + use tempfile::tempdir; + + #[test] + fn build_query_model_removes_stop_words() { + let model = build_query_model("how to find auth token refresh"); + assert!(model.terms.contains(&"auth".to_string())); + assert!(model.terms.contains(&"token".to_string())); + assert!(model.terms.contains(&"refresh".to_string())); + assert!(!model.terms.contains(&"how".to_string())); + assert!(!model.terms.contains(&"find".to_string())); + } + + #[test] + fn score_line_prefers_symbol_definitions() { + let query = build_query_model("refresh token"); + let line = "pub fn refresh_token(session: &Session) -> Result {"; + let cand = score_line(10, line, &query, "rs").expect("line should match"); + assert!(cand.score > 3.0); + assert!(cand.matched_terms.contains(&"refresh".to_string())); + assert!(cand.matched_terms.contains(&"token".to_string())); + } + + #[test] + fn search_project_finds_most_relevant_file() { + let dir = tempdir().unwrap(); + let root = dir.path(); + fs::create_dir_all(root.join("src")).unwrap(); + fs::write( + root.join("src/auth.rs"), + r#" +pub struct Session {} + +pub fn refresh_token(session: &Session) -> String { + format!("new-token-{}", 1) +} +"#, + ) + .unwrap(); + fs::write( + root.join("src/logger.rs"), + r#" +pub fn log_info(msg: &str) { + println!("{}", msg); +} +"#, + ) + .unwrap(); + + let query = build_query_model("refresh token session"); + let outcome = search_project(&query, root, 0, 2, None, 256 * 1024, 0).unwrap(); + + assert!(!outcome.hits.is_empty()); + assert_eq!(outcome.hits[0].path, "src/auth.rs"); + } + + #[test] + fn matches_file_type_aliases() { + let p = Path::new("src/app.tsx"); + assert!(matches_file_type(p, "ts")); + assert!(matches_file_type(p, "typescript")); + assert!(!matches_file_type(p, "rust")); + } + + #[test] + fn truncate_chars_handles_unicode() { + let s = "Привет это длинная строка для теста"; + let truncated = truncate_chars(s, 10); + assert!(truncated.chars().count() <= 10); + } + + // FIX: stem_token must preserve trailing 'e' for common code identifiers + #[test] + fn stem_token_preserves_trailing_e() { + assert_eq!(stem_token("caches"), "cache"); + assert_eq!(stem_token("services"), "service"); + assert_eq!(stem_token("changes"), "change"); + assert_eq!(stem_token("images"), "image"); + assert_eq!(stem_token("packages"), "package"); + assert_eq!(stem_token("interfaces"), "interface"); + assert_eq!(stem_token("sources"), "source"); + } + + #[test] + fn stem_token_handles_regular_suffixes() { + assert_eq!(stem_token("tokens"), "token"); + assert_eq!(stem_token("running"), "runn"); + assert_eq!(stem_token("created"), "creat"); + } + + // FIX: is_comment_line respects file extension — no false positives on .md/.yaml + #[test] + fn is_comment_line_ignores_hash_in_non_script_files() { + assert!(!is_comment_line("# Installation", "md")); + assert!(!is_comment_line("## API Reference", "md")); + assert!(!is_comment_line("# yaml comment", "yaml")); + assert!(!is_comment_line("#[derive(Debug)]", "rs")); + assert!(!is_comment_line("# toml section", "toml")); + } + + #[test] + fn is_comment_line_detects_hash_in_script_files() { + assert!(is_comment_line("# python comment", "py")); + assert!(is_comment_line("# shell comment", "sh")); + assert!(is_comment_line("# ruby comment", "rb")); + } + + #[test] + fn is_comment_line_detects_universal_comment_markers() { + assert!(is_comment_line("// rust comment", "rs")); + assert!(is_comment_line("/* block comment */", "js")); + assert!(is_comment_line("-- sql comment", "sql")); + } + + #[test] + fn resolve_grepai_project_dir_for_directory_path() { + let dir = tempdir().unwrap(); + assert_eq!(resolve_grepai_project_dir(dir.path()), dir.path()); + } + + #[test] + fn resolve_grepai_project_dir_for_file_path_uses_parent() { + let dir = tempdir().unwrap(); + let file = dir.path().join("mod.rs"); + fs::write(&file, "pub fn x() {}").unwrap(); + assert_eq!(resolve_grepai_project_dir(&file), dir.path()); + } +} diff --git a/src/tracking.rs b/src/tracking.rs index eb2acf5..0408ab7 100644 --- a/src/tracking.rs +++ b/src/tracking.rs @@ -37,6 +37,30 @@ use std::ffi::OsString; use std::path::PathBuf; use std::time::Instant; +// ── Project path helpers ── // added: project-scoped tracking support + +/// Get the canonical project path string for the current working directory. +fn current_project_path_string() -> String { + std::env::current_dir() + .ok() + .and_then(|p| p.canonicalize().ok()) + .map(|p| p.to_string_lossy().to_string()) + .unwrap_or_default() +} + +/// Build SQL filter params for project-scoped queries. +/// Returns (exact_match, glob_prefix) for WHERE clause. +/// Uses GLOB instead of LIKE to avoid `_` and `%` in paths acting as wildcards. // changed: GLOB +fn project_filter_params(project_path: Option<&str>) -> (Option, Option) { + match project_path { + Some(p) => ( + Some(p.to_string()), + Some(format!("{}{}*", p, std::path::MAIN_SEPARATOR)), // changed: GLOB pattern with * wildcard + ), + None => (None, None), + } +} + /// Number of days to retain tracking history before automatic cleanup. const HISTORY_DAYS: i64 = 90; @@ -251,6 +275,30 @@ impl Tracker { "ALTER TABLE commands ADD COLUMN exec_time_ms INTEGER DEFAULT 0", [], ); + // Migration: add project_path column with DEFAULT '' for new rows // changed: added DEFAULT + let _ = conn.execute( + "ALTER TABLE commands ADD COLUMN project_path TEXT DEFAULT ''", + [], + ); + // One-time migration: normalize NULLs from pre-default schema // changed: guarded with EXISTS + let has_nulls: bool = conn + .query_row( + "SELECT EXISTS(SELECT 1 FROM commands WHERE project_path IS NULL)", + [], + |row| row.get(0), + ) + .unwrap_or(false); + if has_nulls { + let _ = conn.execute( + "UPDATE commands SET project_path = '' WHERE project_path IS NULL", + [], + ); + } + // Index for fast project-scoped gain queries // added + let _ = conn.execute( + "CREATE INDEX IF NOT EXISTS idx_project_path_timestamp ON commands(project_path, timestamp)", + [], + ); Ok(Self { conn }) } @@ -292,13 +340,16 @@ impl Tracker { 0.0 }; + let project_path = current_project_path_string(); // added: record cwd + self.conn.execute( - "INSERT INTO commands (timestamp, original_cmd, rtk_cmd, input_tokens, output_tokens, saved_tokens, savings_pct, exec_time_ms) - VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8)", + "INSERT INTO commands (timestamp, original_cmd, rtk_cmd, project_path, input_tokens, output_tokens, saved_tokens, savings_pct, exec_time_ms) + VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9)", // added: project_path params![ Utc::now().to_rfc3339(), original_cmd, rtk_cmd, + project_path, // added input_tokens as i64, output_tokens as i64, saved as i64, @@ -340,6 +391,15 @@ impl Tracker { /// # Ok::<(), anyhow::Error>(()) /// ``` pub fn get_summary(&self) -> Result { + self.get_summary_filtered(None) // delegate to filtered variant + } + + /// Get summary statistics filtered by project path. // added + /// + /// When `project_path` is `Some`, matches the exact working directory + /// or any subdirectory (prefix match with path separator). + pub fn get_summary_filtered(&self, project_path: Option<&str>) -> Result { + let (project_exact, project_glob) = project_filter_params(project_path); // added let mut total_commands = 0usize; let mut total_input = 0usize; let mut total_output = 0usize; @@ -347,10 +407,13 @@ impl Tracker { let mut total_time_ms = 0u64; let mut stmt = self.conn.prepare( - "SELECT input_tokens, output_tokens, saved_tokens, exec_time_ms FROM commands", + "SELECT input_tokens, output_tokens, saved_tokens, exec_time_ms + FROM commands + WHERE (?1 IS NULL OR project_path = ?1 OR project_path GLOB ?2)", // added: project filter )?; - let rows = stmt.query_map([], |row| { + let rows = stmt.query_map(params![project_exact, project_glob], |row| { + // added: params Ok(( row.get::<_, i64>(0)? as usize, row.get::<_, i64>(1)? as usize, @@ -380,8 +443,8 @@ impl Tracker { 0 }; - let by_command = self.get_by_command()?; - let by_day = self.get_by_day()?; + let by_command = self.get_by_command(project_path)?; // added: pass project filter + let by_day = self.get_by_day(project_path)?; // added: pass project filter Ok(GainSummary { total_commands, @@ -396,16 +459,22 @@ impl Tracker { }) } - fn get_by_command(&self) -> Result> { + fn get_by_command( + &self, + project_path: Option<&str>, // added + ) -> Result> { + let (project_exact, project_glob) = project_filter_params(project_path); // added let mut stmt = self.conn.prepare( "SELECT rtk_cmd, COUNT(*), SUM(saved_tokens), AVG(savings_pct), AVG(exec_time_ms) FROM commands + WHERE (?1 IS NULL OR project_path = ?1 OR project_path GLOB ?2) GROUP BY rtk_cmd ORDER BY SUM(saved_tokens) DESC - LIMIT 10", + LIMIT 10", // added: project filter in WHERE )?; - let rows = stmt.query_map([], |row| { + let rows = stmt.query_map(params![project_exact, project_glob], |row| { + // added: params Ok(( row.get::<_, String>(0)?, row.get::<_, i64>(1)? as usize, @@ -418,16 +487,22 @@ impl Tracker { Ok(rows.collect::, _>>()?) } - fn get_by_day(&self) -> Result> { + fn get_by_day( + &self, + project_path: Option<&str>, // added + ) -> Result> { + let (project_exact, project_glob) = project_filter_params(project_path); // added let mut stmt = self.conn.prepare( "SELECT DATE(timestamp), SUM(saved_tokens) FROM commands + WHERE (?1 IS NULL OR project_path = ?1 OR project_path GLOB ?2) GROUP BY DATE(timestamp) ORDER BY DATE(timestamp) DESC - LIMIT 30", + LIMIT 30", // added: project filter in WHERE )?; - let rows = stmt.query_map([], |row| { + let rows = stmt.query_map(params![project_exact, project_glob], |row| { + // added: params Ok((row.get::<_, String>(0)?, row.get::<_, i64>(1)? as usize)) })?; @@ -455,6 +530,12 @@ impl Tracker { /// # Ok::<(), anyhow::Error>(()) /// ``` pub fn get_all_days(&self) -> Result> { + self.get_all_days_filtered(None) // delegate to filtered variant + } + + /// Get daily statistics filtered by project path. // added + pub fn get_all_days_filtered(&self, project_path: Option<&str>) -> Result> { + let (project_exact, project_glob) = project_filter_params(project_path); // added let mut stmt = self.conn.prepare( "SELECT DATE(timestamp) as date, @@ -464,11 +545,13 @@ impl Tracker { SUM(saved_tokens) as saved, SUM(exec_time_ms) as total_time FROM commands + WHERE (?1 IS NULL OR project_path = ?1 OR project_path GLOB ?2) GROUP BY DATE(timestamp) - ORDER BY DATE(timestamp) DESC", + ORDER BY DATE(timestamp) DESC", // added: project filter )?; - let rows = stmt.query_map([], |row| { + let rows = stmt.query_map(params![project_exact, project_glob], |row| { + // added: params let input = row.get::<_, i64>(2)? as usize; let saved = row.get::<_, i64>(4)? as usize; let commands = row.get::<_, i64>(1)? as usize; @@ -520,6 +603,12 @@ impl Tracker { /// # Ok::<(), anyhow::Error>(()) /// ``` pub fn get_by_week(&self) -> Result> { + self.get_by_week_filtered(None) // delegate to filtered variant + } + + /// Get weekly statistics filtered by project path. // added + pub fn get_by_week_filtered(&self, project_path: Option<&str>) -> Result> { + let (project_exact, project_glob) = project_filter_params(project_path); // added let mut stmt = self.conn.prepare( "SELECT DATE(timestamp, 'weekday 0', '-6 days') as week_start, @@ -530,11 +619,13 @@ impl Tracker { SUM(saved_tokens) as saved, SUM(exec_time_ms) as total_time FROM commands + WHERE (?1 IS NULL OR project_path = ?1 OR project_path GLOB ?2) GROUP BY week_start - ORDER BY week_start DESC", + ORDER BY week_start DESC", // added: project filter )?; - let rows = stmt.query_map([], |row| { + let rows = stmt.query_map(params![project_exact, project_glob], |row| { + // added: params let input = row.get::<_, i64>(3)? as usize; let saved = row.get::<_, i64>(5)? as usize; let commands = row.get::<_, i64>(2)? as usize; @@ -587,6 +678,12 @@ impl Tracker { /// # Ok::<(), anyhow::Error>(()) /// ``` pub fn get_by_month(&self) -> Result> { + self.get_by_month_filtered(None) // delegate to filtered variant + } + + /// Get monthly statistics filtered by project path. // added + pub fn get_by_month_filtered(&self, project_path: Option<&str>) -> Result> { + let (project_exact, project_glob) = project_filter_params(project_path); // added let mut stmt = self.conn.prepare( "SELECT strftime('%Y-%m', timestamp) as month, @@ -596,11 +693,13 @@ impl Tracker { SUM(saved_tokens) as saved, SUM(exec_time_ms) as total_time FROM commands + WHERE (?1 IS NULL OR project_path = ?1 OR project_path GLOB ?2) GROUP BY month - ORDER BY month DESC", + ORDER BY month DESC", // added: project filter )?; - let rows = stmt.query_map([], |row| { + let rows = stmt.query_map(params![project_exact, project_glob], |row| { + // added: params let input = row.get::<_, i64>(2)? as usize; let saved = row.get::<_, i64>(4)? as usize; let commands = row.get::<_, i64>(1)? as usize; @@ -655,23 +754,37 @@ impl Tracker { /// # Ok::<(), anyhow::Error>(()) /// ``` pub fn get_recent(&self, limit: usize) -> Result> { + self.get_recent_filtered(limit, None) // delegate to filtered variant + } + + /// Get recent command history filtered by project path. // added + pub fn get_recent_filtered( + &self, + limit: usize, + project_path: Option<&str>, + ) -> Result> { + let (project_exact, project_glob) = project_filter_params(project_path); // added let mut stmt = self.conn.prepare( "SELECT timestamp, rtk_cmd, saved_tokens, savings_pct FROM commands + WHERE (?1 IS NULL OR project_path = ?1 OR project_path GLOB ?2) ORDER BY timestamp DESC - LIMIT ?1", + LIMIT ?3", // added: project filter )?; - let rows = stmt.query_map(params![limit as i64], |row| { - Ok(CommandRecord { - timestamp: DateTime::parse_from_rfc3339(&row.get::<_, String>(0)?) - .map(|dt| dt.with_timezone(&Utc)) - .unwrap_or_else(|_| Utc::now()), - rtk_cmd: row.get(1)?, - saved_tokens: row.get::<_, i64>(2)? as usize, - savings_pct: row.get(3)?, - }) - })?; + let rows = stmt.query_map( + params![project_exact, project_glob, limit as i64], // added: project params + |row| { + Ok(CommandRecord { + timestamp: DateTime::parse_from_rfc3339(&row.get::<_, String>(0)?) + .map(|dt| dt.with_timezone(&Utc)) + .unwrap_or_else(|_| Utc::now()), + rtk_cmd: row.get(1)?, + saved_tokens: row.get::<_, i64>(2)? as usize, + savings_pct: row.get(3)?, + }) + }, + )?; Ok(rows.collect::, _>>()?) } @@ -1037,4 +1150,42 @@ mod tests { let db_path = get_db_path().expect("Failed to get db path"); assert!(db_path.ends_with("rtk/history.db")); } + + // 9. project_filter_params uses GLOB pattern with * wildcard // added + #[test] + fn test_project_filter_params_glob_pattern() { + let (exact, glob) = project_filter_params(Some("/home/user/project")); + assert_eq!(exact.unwrap(), "/home/user/project"); + // Must use * (GLOB) not % (LIKE) for subdirectory prefix matching + let glob_val = glob.unwrap(); + assert!(glob_val.ends_with('*'), "GLOB pattern must end with *"); + assert!(!glob_val.contains('%'), "Must not contain LIKE wildcard %"); + assert_eq!( + glob_val, + format!("/home/user/project{}*", std::path::MAIN_SEPARATOR) + ); + } + + // 10. project_filter_params returns None for None input // added + #[test] + fn test_project_filter_params_none() { + let (exact, glob) = project_filter_params(None); + assert!(exact.is_none()); + assert!(glob.is_none()); + } + + // 11. GLOB pattern safe with underscores in path names // added + #[test] + fn test_project_filter_params_underscore_safe() { + // In LIKE, _ matches any single char; in GLOB, _ is literal + let (exact, glob) = project_filter_params(Some("/home/user/my_project")); + assert_eq!(exact.unwrap(), "/home/user/my_project"); + let glob_val = glob.unwrap(); + // _ must be preserved literally (GLOB treats _ as literal, LIKE does not) + assert!(glob_val.contains("my_project")); + assert_eq!( + glob_val, + format!("/home/user/my_project{}*", std::path::MAIN_SEPARATOR) + ); + } }