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 40%
Model-judged precision N/A
F1 N/A
Tier 1 recall 33.3%
Tier 2 recall 28.6%
Tier 3 recall 50%
Tier 4 recall 50%
Security recall 50%
Defect recall 53.8%
Maintainability recall 0%
Performance recall 0%
Median anchor distance 0
Worst anchor distance 0
Refusals a judge overturned Not recorded

Review outcomes

Distinct matched defects 8
Defects missed 12
Findings 8
Unkeyed findings 0
Intended findings 0
Carried findings Not recorded

Cost, usage, and speed

Total bill $0.0154
Review bill $0.0154
Judge bill N/A
Tokens 37579
Duration 3m 54s

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-e88d02a8e3762967
Build ID
build-4ceb7cbd44e9619b
Cohort ID
cohort-b65e5ff0e0bc5ce2
Harness
bench 1 / 10b3b2068100b7ba429855e062500eaf83b90120 dirty
Adapter
afi 1 / sha256:a1a935298956020ee6d767a756847abb4c00694c88c2eb80d454886ebc4acf8c
Exit code
0
Wall time
234
Deadline exceeded
No
Budget
Not recorded
Billing limit
$2.00

Usage

Normalized reviewer-tool usage projection

Input tokens
36967
Output tokens
612
Cached input
67264
Reasoning tokens
15667
Requests
4
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

A dry run is destructive. The blob unlink is guarded by `if !dry_run` (line 125), but every "removed" candidate is still pushed to `gone` and `forget(&index, &gone)` is called unconditionally, deleting index entry files (lines 249-257). `?dry_run=true`, documented as reporting "without removing anything" (sweep.rs:87-88, docs/operations.md), actually deletes index entries for every blob the hypothetical sweep would take — which, on an over-ceiling store, is most of the index.

bug
Category: bug Confidence: Not recorded

services/proxy/src/sweep.rs:140

Evidence quote

Not recorded

Suggested fix

Not recorded

matchedDefect 12 (locality)
Finding f2

bug

The two sweep counters are swapped in the exposition. `COUNTERS` lists `sweep_blobs_removed` then `sweep_bytes_reclaimed` (metrics.rs:51-56), but `values()` returns `sweep_bytes_reclaimed` then `sweep_blobs_removed` (lines 94-95), and `render` zips them in order. `cairn_proxy_sweep_blobs_removed_total` reports bytes and vice versa, so an operator alerting on reclaimed bytes per docs/operations.md reads blob counts.

bug
Category: bug Confidence: Not recorded

services/proxy/src/metrics.rs:94

Evidence quote

Not recorded

Suggested fix

Not recorded

matchedDefect 13 (locality)
Finding f3

bug

clear_partials` unlinks every file in `incoming` with no age check, but `incoming` also holds the temp files of fetches in flight right now (`BlobStore::writer`, store.rs:171-180). The fetch keeps writing to the unlinked inode and then fails at commit — `fs::rename` on the missing temp (store.rs:259) — turning a healthy download into a 500. A periodic sweep simply kills any download that happens to be running, which is exactly what `CAIRN_CACHE_MIN_AGE` exists to prevent.

bug
Category: bug Confidence: Not recorded

services/proxy/src/sweep.rs:232

Evidence quote

Not recorded

Suggested fix

Not recorded

matchedDefect 17 (locality)
Finding f4

bug

Blobs with no index entry are removed with `min_age` deliberately bypassed, but a just-committed blob has no index entry for the whole commit → `register_version` (network round trip) → `link`… Blobs with no index entry are removed with `min_age` deliberately bypassed, but a just-committed blob has no index entry for the whole commit → `register_version` (network round trip) → `link` window (routes/cache.rs:151-163). A sweep in that window deletes the blob; the serve path then fails at cache.rs:90 with "a blob committed by this request is already missing" (500), and the client's fetch is wasted. The registry call makes the window wide, and the grace period the docs promise does not cover it.

bug
Category: bug Confidence: Not recorded

services/proxy/src/sweep.rs:119

Evidence quote

Not recorded

Suggested fix

Not recorded

matchedDefect 18 (locality)
Finding f5

bug

A failed `fs::remove_file` is still counted as success: `remaining`, `bytes`, `removed` and `gone` are all updated on the error path, and `forget` then deletes the index entry for a blob that may… A failed `fs::remove_file` is still counted as success: `remaining`, `bytes`, `removed` and `gone` are all updated on the error path, and `forget` then deletes the index entry for a blob that may still be on disk. The metrics overstate reclamation, `remaining` drops for bytes never freed so the sweep stops early believing it is under the ceiling, and a persistent unlink failure (permissions, read-only remount) looks like a successful sweep.

bug
Category: bug Confidence: Not recorded

services/proxy/src/sweep.rs:126

Evidence quote

Not recorded

Suggested fix

Not recorded

matchedDefect 2 (locality)
Finding f6

bug

fs::metadata` follows symlinks, contradicting the comment at lines 160-163 which claims links are "counted at the size of the link" (that needs `fs::symlink_metadata`). Worse, a symlink to a directory passes the `is_dir` check at line 167 and is recursed into, so a symlink cycle in `blobs/` or `index/` makes `collect` recurse forever — the store-moved-between-volumes scenario the comment anticipates is the one that hangs the sweep.

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

performance

The synchronous full-store walk runs directly on a tokio worker thread — both from the interval task (`run().await`) and from the admin handler (routes/admin.rs:76). On a store the module doc itself sizes at tens of thousands of directories, one sweep blocks that worker for the whole walk and stalls every request scheduled on it; nothing moves the walk to `spawn_blocking`.

performance
Category: performance Confidence: Not recorded

services/proxy/src/sweep.rs:84

Evidence quote

Not recorded

Suggested fix

Not recorded

matchedDefect 11 (locality)
Finding f8

bug

A blob whose mtime is ahead of the local clock gets `age = 0` via `unwrap_or_default`, so it never satisfies `age >= min_age` (line 120) and is permanently immune to ceiling eviction. Clock skew on a shared volume — the case the comment describes — can therefore make it impossible to bring the store under `CAIRN_CACHE_MAX_BYTES` at all.

bug
Category: bug Confidence: Not recorded

services/proxy/src/sweep.rs:189

Evidence quote

Not recorded

Suggested fix

Not recorded

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