atagen

roundabout

public
Star0
Watch0

Commit 7770b8fcfa8b

tarball

atagen <boss@atagen.co>2026-10-25 11:09 UTC

1 file changed+21-5
artifacts: re-measure before reporting over cap

A cached size can predate a manual rm by up to size_ttl, so the stop hook kept telling every agent in a project to gc --cap for ten minutes after it was already under. An over verdict now re-measures entries older than RECHECK_SECS first, which only costs a walk when something looks over.
Modified file: src/artifacts.rs+21 additions−5 deletions
@@ -146,15 +146,14 @@ fn active_roots() -> BTreeSet<PathBuf> {
146146 }
147147 }
148148
149-fn refresh(cfg: &Config, root: Option<&Path>, fresh: bool) -> Registry {
149+fn refresh(cfg: &Config, root: Option<&Path>, max_age: u64) -> Registry {
150150 if let Some(root) = root {
151151 register(cfg, root, false);
152152 }
153- let ttl = cfg.artifacts.size_ttl.0.as_secs();
154153 store::update("artifacts", |reg: &mut Registry| {
155154 reg.retain(|p, _| fs::symlink_metadata(p).is_ok());
156155 for (path, e) in reg.iter_mut() {
157- if fresh || now().saturating_sub(e.sized_at) > ttl {
156+ if now().saturating_sub(e.sized_at) >= max_age {
158157 e.size = size_of(path);
159158 e.sized_at = now();
160159 }
@@ -198,8 +197,25 @@ impl Report {
198197 }
199198 }
200199
200+const RECHECK_SECS: u64 = 60;
201+
202+/// the cache can predate someone's `rm`, so being over earns a second look
203+/// before anyone gets nagged
201204 pub fn check(cfg: &Config, root: Option<&Path>, fresh: bool) -> Report {
202- let entries = refresh(cfg, root, fresh);
205+ let ttl = if fresh {
206+ 0
207+ } else {
208+ cfg.artifacts.size_ttl.0.as_secs()
209+ };
210+ let report = measure(cfg, root, ttl);
211+ if report.over() && ttl > RECHECK_SECS {
212+ return measure(cfg, root, RECHECK_SECS);
213+ }
214+ report
215+}
216+
217+fn measure(cfg: &Config, root: Option<&Path>, max_age: u64) -> Report {
218+ let entries = refresh(cfg, root, max_age);
203219 let global = entries.values().map(|e| e.size).sum();
204220 let project = root.map(|r| {
205221 let size = entries
@@ -252,7 +268,7 @@ pub struct Gc {
252268 }
253269
254270 pub fn gc(cfg: &Config, to_cap: bool, dry_run: bool) -> Gc {
255- let entries = refresh(cfg, None, false);
271+ let entries = refresh(cfg, None, cfg.artifacts.size_ttl.0.as_secs());
256272 let active = active_roots();
257273 let idle_after = cfg.artifacts.idle_after.0.as_secs();
258274 let movable = |e: &Entry| !e.pinned && !active.contains(&e.root);