A background lane that runs longer than ~1 hour cannot push its own work: the GitHub App installation token injected at dispatch has a 1-hour TTL, and lanes routinely run longer.
Observed tonight: a lane ran ~70 minutes, finished cleanly with a fully tested implementation committed locally — then hit Bad credentials on both git push and gh api, and ended by asking a human to refresh the token. The work survived only because the commit was recoverable from the object store by SHA; the worktree and its branch had already been removed on exit (#1132).
This is distinct from #1126 (token absent): here the token was present and correct at dispatch and simply aged out mid-run. It gets worse as lanes get longer, and it silently converts finished work into a manual salvage.
Fix direction: mint the installation token lazily/refreshably rather than once at dispatch — re-mint on demand when a git/gh operation returns 401, or refresh on a timer well inside the TTL. The mint itself is small (JWT sign → POST /app/installations/{id}/access_tokens); the problem is purely that it happens once, at the start.
Acceptance: a lane running 2+ hours can still git push and open a PR as the bot at the end, with no human refresh.
A background lane that runs longer than ~1 hour cannot push its own work: the GitHub App installation token injected at dispatch has a 1-hour TTL, and lanes routinely run longer.
Observed tonight: a lane ran ~70 minutes, finished cleanly with a fully tested implementation committed locally — then hit
Bad credentialson bothgit pushandgh api, and ended by asking a human to refresh the token. The work survived only because the commit was recoverable from the object store by SHA; the worktree and its branch had already been removed on exit (#1132).This is distinct from #1126 (token absent): here the token was present and correct at dispatch and simply aged out mid-run. It gets worse as lanes get longer, and it silently converts finished work into a manual salvage.
Fix direction: mint the installation token lazily/refreshably rather than once at dispatch — re-mint on demand when a git/gh operation returns 401, or refresh on a timer well inside the TTL. The mint itself is small (JWT sign →
POST /app/installations/{id}/access_tokens); the problem is purely that it happens once, at the start.Acceptance: a lane running 2+ hours can still
git pushand open a PR as the bot at the end, with no human refresh.