Session summary

default

scored

afi / afi · cli reviewed proxy at 9b51f95e with Default profile / DeepSeek · v4 pro high on afi 0.30.0

Measurements

Unavailable values retain their exported state and reason

Quality

Recall 25%
Model-judged precision N/A
F1 N/A
Tier 1 recall 100%
Tier 2 recall 0%
Tier 3 recall 33.3%
Tier 4 recall 0%
Security recall 0%
Defect recall 38.5%
Maintainability recall 0%
Performance recall 0%
Median anchor distance 0
Worst anchor distance 3
Refusals a judge overturned Not recorded

Review outcomes

Distinct matched defects 5
Defects missed 15
Findings 5
Unkeyed findings 0
Intended findings 0
Carried findings Not recorded

Cost, usage, and speed

Total bill $0.1082
Review bill $0.1082
Judge bill N/A
Tokens 60316
Duration 3m 9s

Execution and identity

Lifecycle, reviewer, build, settings, and normalized execution limits

Lifecycle
completed
Lifecycle reason
Not recorded
Started
Finished
Reviewer
afi
Reviewer tool
afi · cli
Configuration
default / f8fe6f35adbe
Configuration ID
config-79001f276ea3730f
Build
afi 0.30.0 / b0f313c0b59a66ecc7612396dc8db0ea5da13a7a
Comparison
comparison-27233269bfca96e3
Build ID
build-4ceb7cbd44e9619b
Cohort ID
cohort-b65e5ff0e0bc5ce2
Harness
bench 1 / 10b3b2068100b7ba429855e062500eaf83b90120 dirty
Adapter
afi 1 / sha256:a1a935298956020ee6d767a756847abb4c00694c88c2eb80d454886ebc4acf8c
Exit code
0
Wall time
189
Deadline exceeded
No
Budget
$2.00
Billing limit
$2.00

Usage

Normalized reviewer-tool usage projection

Input tokens
58926
Output tokens
1390
Cached input
13824
Reasoning tokens
1145
Requests
3
Models counted
Not recorded

Judge

Normalized assessment summary

Judge data is N/A for this run

Findings

Review text is escaped; normalized decisions follow each finding

Finding f1

bug

In `sweep()`, `remaining` is initialised to `held` (sum of all candidate sizes) but the loop subtracts `candidate.size` only for removed blobs. The condition `remaining >= self.max_bytes` at line 120 never becomes false once the total drops below the ceiling, so the loop stops removing *age-eligible* blobs after enough unreferenced ones are removed — but it does not stop removing unreferenced blobs (the first disjunct `!index.contains_key(hex)` is always true for them). This is actually the intended behaviour. However, the real bug is that `remaining` is never decremented for blobs that are *skipped* (referenced + under ceiling, or referenced + too young). The `remaining` variable is meant to track how much of the store's total is still present after removals, but it only subtracts removed blobs. Since `remaining` starts at `held` and only goes down on removals, the condition `remaining >= self.max_bytes` will become false at the right point — the logic is correct as written. No bug here on closer inspection.

bug
Category: bug Confidence: Not recorded

services/proxy/src/sweep.rs:105-106

Evidence quote

Not recorded

Suggested fix

Not recorded

matchedDefect 1 (locality)
Finding f2

bug

The `values()` method returns `sweep_bytes_reclaimed` at index 4 and `sweep_blobs_removed` at index 5, but the `COUNTERS` array at line 50-57 has `sweep_blobs_removed` at index 4 and… The `values()` method returns `sweep_bytes_reclaimed` at index 4 and `sweep_blobs_removed` at index 5, but the `COUNTERS` array at line 50-57 has `sweep_blobs_removed` at index 4 and `sweep_bytes_reclaimed` at index 5. The `render()` method zips them in order, so the metric named `cairn_proxy_sweep_blobs_removed_total` will display the byte count, and `cairn_proxy_sweep_bytes_reclaimed_total` will display the blob count — the two counters are swapped in the Prometheus exposition.

bug
Category: bug Confidence: Not recorded

services/proxy/src/metrics.rs:94-95

Evidence quote

Not recorded

Suggested fix

Not recorded

matchedDefect 13 (locality)
Finding f3

bug

sweep()` is a synchronous `&self` method that calls `clear_partials` and `referenced` (which both do filesystem I/O) while the `Mutex` lock is held (acquired by `run()` at line 83). This is intentional per the module doc — the walk is synchronous to avoid `tokio::fs` overhead. However, `run()` holds the `tokio::sync::Mutex` across the entire synchronous `sweep()` call. A `tokio::sync::Mutex` is designed to be held across `.await` points; holding it across a long synchronous operation (a full filesystem walk of a large store) will block the async runtime's worker thread, preventing other tasks from making progress on that thread. The comment on line 83 says "waiting for any sweep already under way to finish first" — the `std::sync::Mutex` would be more appropriate here since the guard is never held across an await point, or the synchronous work should be spawned onto `tokio::task::spawn_blocking`.

bug
Category: bug Confidence: Not recorded

services/proxy/src/sweep.rs:90-91

Evidence quote

Not recorded

Suggested fix

Not recorded

matchedDefect 11 (locality)
Finding f4

bug

The removal condition `!index.contains_key(hex) || (remaining >= self.max_bytes && candidate.age >= self.min_age)` uses `remaining >= self.max_bytes` rather than `remaining > self.max_bytes`. The intent stated in the config comment is "the most the blob store may hold" and "removes the oldest blobs until the store is back within it." With `>=`, a store sitting exactly at the ceiling will have every age-eligible blob removed until `remaining` drops below the ceiling, which is correct. But combined with the fact that `remaining` is compared against `self.max_bytes` (the target ceiling) rather than being checked after each removal against whether the store is now *under* the ceiling, the `>=` is fine. No actual bug here.

bug
Category: bug Confidence: Not recorded

services/proxy/src/sweep.rs:119-120

Evidence quote

Not recorded

Suggested fix

Not recorded

matchedDefect 3 (locality)
Finding f5

bug

When a blob is removed (even when `remove_file` fails, e.g. because the file was already gone), `remaining` is decremented by `candidate.size`, `bytes` is incremented by `candidate.size`, and… When a blob is removed (even when `remove_file` fails, e.g. because the file was already gone), `remaining` is decremented by `candidate.size`, `bytes` is incremented by `candidate.size`, and `removed` is incremented. If `remove_file` fails, the blob's bytes were not actually reclaimed (the file was already gone), yet the `Reclaimed` struct reports them as reclaimed bytes and the metrics counter `sweep_bytes_reclaimed` is incremented by that amount. The metrics will overcount reclaimed bytes. No findings.

bug
Category: bug Confidence: Not recorded

services/proxy/src/sweep.rs:134

Evidence quote

Not recorded

Suggested fix

Not recorded

matchedDefect 2 (locality)

Source artifacts

Open a row to inspect or download evidence from this atomically published local run

findings present

Open verified source artifact

Open this path at the exported commit

The artifact is present; its content is available through the verified source link

meta present

Open verified source artifact

Open this path at the exported commit

The artifact is present; its content is available through the verified source link

record present

Open verified source artifact

Open this path at the exported commit

The artifact is present; its content is available through the verified source link

result present

Open verified source artifact

Open this path at the exported commit

The artifact is present; its content is available through the verified source link

spend present

Open verified source artifact

Open this path at the exported commit

The artifact is present; its content is available through the verified source link

stderr present

Open verified source artifact

Open this path at the exported commit

The artifact is present; its content is available through the verified source link

summary present

Open verified source artifact

Open this path at the exported commit

The artifact is present; its content is available through the verified source link

traffic present

Open verified source artifact

Open this path at the exported commit

The artifact is present; its content is available through the verified source link

benchee benchee-dashboard-1 built from 10f4ec58 Static benchmark evidence ·