🤖 agent issue
Two observations from dogfooding #1603 (PR #1603), neither blocking it.
1. The adoption pass scales as runs × claude/* heads. For every waiting web run, descendsFrom runs cat-file -e (+ a fetch when the object is not local) and merge-base --is-ancestor against every claude/* head on origin — and nothing prunes those heads (the scratch sweep deletes cloud-* and tf-agent-* only). On an active repo that is dozens of heads within weeks; a run whose session never pushes is re-checked against all of them every pass for 48 h. The fetch also has no destination refspec, so the objects land in FETCH_HEAD only and get re-fetched after gc. Cheaper shape: one git fetch origin '+refs/heads/claude/*:refs/remotes/origin/claude/*' per pass, then one git for-each-ref --contains=<anchor> refs/remotes/origin/claude/ per run (which also answers the exactly-one question in one call). Same family: listAgents parses every archived record each pass to find the few web runs inside the window — the id is a timestamp, so the filename alone rejects the rest before any read.
2. The daemon clock merges ticks while a job is slow, so every cadence stretches. startDaemonTick counts a tick only when one actually runs; an interval firing while a tick is in flight joins it. With a job that takes long — seen: the data sync of an SSH-remote project whose agent has no identities, failing slowly every minute — the 20-tick adoption cadence became ~26 minutes (pass at 10:50:46, next at 11:16:57). Every every: N job is affected, not just adoption. Either count wall-clock rather than executed ticks, or time-box the per-job turn.
Context: #1601, the pass lives in src/cloud-work.ts, the clock in src/daemon-tick.ts.
🤖 agent issue
Two observations from dogfooding #1603 (PR #1603), neither blocking it.
1. The adoption pass scales as runs ×
claude/*heads. For every waiting web run,descendsFromrunscat-file -e(+ afetchwhen the object is not local) andmerge-base --is-ancestoragainst everyclaude/*head on origin — and nothing prunes those heads (the scratch sweep deletescloud-*andtf-agent-*only). On an active repo that is dozens of heads within weeks; a run whose session never pushes is re-checked against all of them every pass for 48 h. The fetch also has no destination refspec, so the objects land inFETCH_HEADonly and get re-fetched after gc. Cheaper shape: onegit fetch origin '+refs/heads/claude/*:refs/remotes/origin/claude/*'per pass, then onegit for-each-ref --contains=<anchor> refs/remotes/origin/claude/per run (which also answers the exactly-one question in one call). Same family:listAgentsparses every archived record each pass to find the few web runs inside the window — the id is a timestamp, so the filename alone rejects the rest before any read.2. The daemon clock merges ticks while a job is slow, so every cadence stretches.
startDaemonTickcounts a tick only when one actually runs; an interval firing while a tick is in flight joins it. With a job that takes long — seen: the data sync of an SSH-remote project whose agent has no identities, failing slowly every minute — the 20-tick adoption cadence became ~26 minutes (pass at 10:50:46, next at 11:16:57). Everyevery: Njob is affected, not just adoption. Either count wall-clock rather than executed ticks, or time-box the per-job turn.Context: #1601, the pass lives in
src/cloud-work.ts, the clock insrc/daemon-tick.ts.