Session summary

default

scored

afi / afi · cli reviewed proxy at 9b51f95e with Default profile / Z.AI · glm 5.3 flash high on afi 0.30.0

Measurements

Unavailable values retain their exported state and reason

Quality

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

Review outcomes

Distinct matched defects 9
Defects missed 11
Findings 9
Unkeyed findings 0
Intended findings 0
Carried findings Not recorded

Cost, usage, and speed

Total bill $0.0317
Review bill $0.0317
Judge bill N/A
Tokens 69713
Duration 5m 6s

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 / be7c5b1aa470
Configuration ID
config-e5f3155850f5053d
Build
afi 0.30.0 / b0f313c0b59a66ecc7612396dc8db0ea5da13a7a
Comparison
comparison-491a157d4c780a6f
Build ID
build-944472ec933601e7
Cohort ID
cohort-fdab2adfb8a4bd39
Harness
bench 1 / d5372b5a9797137af68e35c478f308f58ca4510c dirty
Adapter
afi 1 / sha256:a1a935298956020ee6d767a756847abb4c00694c88c2eb80d454886ebc4acf8c
Exit code
0
Wall time
306
Deadline exceeded
No
Budget
Not recorded
Billing limit
$2.00

Usage

Normalized reviewer-tool usage projection

Input tokens
68640
Output tokens
1073
Cached input
241920
Reasoning tokens
28354
Requests
11
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

values()` reads `sweep_bytes_reclaimed` and `sweep_blobs_removed` in the opposite order to `COUNTERS` (lines 51-57), so the `/metrics` endpoint renders the blob count under… values()` reads `sweep_bytes_reclaimed` and `sweep_blobs_removed` in the opposite order to `COUNTERS` (lines 51-57), so the `/metrics` endpoint renders the blob count under `cairn_proxy_sweep_bytes_reclaimed_total` and the byte count under `cairn_proxy_sweep_blobs_removed_total`. docs/operations.md directs operators to alert on `cairn_proxy_sweep_bytes_reclaimed_total`, so the alert would fire on blobs instead of bytes — the exact mis-rendering the comment at line 30-32 claims the side-by-side layout prevents.

bug
Category: bug Confidence: Not recorded

services/proxy/src/metrics.rs:94

Evidence quote

Not recorded

Suggested fix

Not recorded

matchedDefect 13 (locality)
Finding f2

bug

the admin route calls `app.sweeper.sweep(dry_run)` directly, bypassing the `running` mutex that only `Sweeper::run` (sweep.rs:83) takes. An operator-triggered sweep runs concurrently with the background sweep — exactly the "two of them over one directory" interference the module doc (sweep.rs:10-12) promises the type prevents. Both compute `held`/`remaining` from totals the other is concurrently shrinking, so together they can delete roughly twice the excess, dropping the store far below the ceiling either aimed at.

bug
Category: bug Confidence: Not recorded

services/proxy/src/routes/admin.rs:76

Evidence quote

Not recorded

Suggested fix

Not recorded

matchedDefect 6 (locality)
Finding f3

bug

forget(&index, &gone)` runs unconditionally, but in dry-run mode `gone` is still populated (line 137) while the blob removals were skipped — so `?dry_run=true`, which docs/architecture.md and the… forget(&index, &gone)` runs unconditionally, but in dry-run mode `gone` is still populated (line 137) while the blob removals were skipped — so `?dry_run=true`, which docs/architecture.md and the route doc promise removes "without removing anything", actually deletes the index entries for every blob a sweep would reclaim. Those coordinates then resolve as misses and refetch until relinked, so a "dry" probe churns the cache it was meant to size.

bug
Category: bug Confidence: Not recorded

services/proxy/src/sweep.rs:140

Evidence quote

Not recorded

Suggested fix

Not recorded

matchedDefect 12 (locality)
Finding f4

bug

clear_partials` unlinks every file in `incoming`, including temp files of fetches still in flight — `BlobWriter` (store.rs:171-180) and `BlobStore::link`'s index temp (store.rs:147-152) both live… clear_partials` unlinks every file in `incoming`, including temp files of fetches still in flight — `BlobWriter` (store.rs:171-180) and `BlobStore::link`'s index temp (store.rs:147-152) both live there while active. The unlink doesn't kill the write (the fd stays valid), but `commit`'s rename (store.rs:259) then fails with ENOENT and the client's fully-downloaded artifact returns a storage 500. The comment at lines 220-223 ("A file in `incoming` is a fetch that is not coming back") is wrong for any fetch mid-download when the sweep fires.

bug
Category: bug Confidence: Not recorded

services/proxy/src/sweep.rs:232

Evidence quote

Not recorded

Suggested fix

Not recorded

matchedDefect 17 (locality)
Finding f5

bug

run()` executes the fully synchronous `self.sweep(false)` — a recursive `std::fs` walk that the module doc itself sizes at sixty-five thousand directories — directly on a tokio worker thread. Every cache request stalls behind it for the duration of the walk, and the `running` mutex is held across it so an admin sweep queues too. `spawn_blocking` is the fix the doc argues for and then doesn't apply.

bug
Category: bug Confidence: Not recorded

services/proxy/src/sweep.rs:84

Evidence quote

Not recorded

Suggested fix

Not recorded

matchedDefect 11 (locality)
Finding f6

bug

fs::metadata` follows symlinks, so a linked-in blob is counted at its target's size, contradicting the comment at lines 160-163 which claims `symlink_metadata` behavior; and since `meta.is_dir()`… fs::metadata` follows symlinks, so a linked-in blob is counted at its target's size, contradicting the comment at lines 160-163 which claims `symlink_metadata` behavior; and since `meta.is_dir()` recurses, a symlink loop under `blobs/sha256` makes `collect` recurse until the stack overflows, aborting the process.

bug
Category: bug Confidence: Not recorded

services/proxy/src/sweep.rs:164

Evidence quote

Not recorded

Suggested fix

Not recorded

matchedDefect 4 (locality)
Finding f7

bug

a blob committed at cache.rs:151 is not indexed until `link` at cache.rs:163, with a registry round-trip between; a sweep in that window classifies it as unreferenced and deletes it, so the miss… a blob committed at cache.rs:151 is not indexed until `link` at cache.rs:163, with a registry round-trip between; a sweep in that window classifies it as unreferenced and deletes it, so the miss path's reopen at cache.rs:90-97 fails and the client gets the "blob committed by this request is already missing" 500 instead of the artifact it just downloaded.

bug
Category: bug Confidence: Not recorded

services/proxy/src/sweep.rs:119

Evidence quote

Not recorded

Suggested fix

Not recorded

matchedDefect 18 (locality)
Finding f8

bug

when `fs::remove_file` fails, the blob stays on disk but `remaining`, `bytes`, `removed` and `gone` are all still updated, so the metrics and the route response overcount what was reclaimed and… when `fs::remove_file` fails, the blob stays on disk but `remaining`, `bytes`, `removed` and `gone` are all still updated, so the metrics and the route response overcount what was reclaimed and `forget` (line 140) deletes index entries naming a blob that still exists.

bug
Category: bug Confidence: Not recorded

services/proxy/src/sweep.rs:126

Evidence quote

Not recorded

Suggested fix

Not recorded

matchedDefect 2 (locality)
Finding f9

bug

tokio::time::interval`'s first tick completes immediately, not "one interval away" as the doc comment at lines 101-102 claims — a proxy that restarts sweeps a store it has not yet touched, the… tokio::time::interval`'s first tick completes immediately, not "one interval away" as the doc comment at lines 101-102 claims — a proxy that restarts sweeps a store it has not yet touched, the protection the comment describes does not exist. Skipping the first tick (or sleeping first) would be needed for the stated behaviour.

bug
Category: bug Confidence: Not recorded

services/proxy/src/main.rs:108

Evidence quote

Not recorded

Suggested fix

Not recorded

matchedDefect 7 (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 ·