hire-an-agent now adds the new Forgejo user as a `write` collaborator on
`$FORGE_REPO` right after the token step, mirroring the collaborator setup
lib/forge-setup.sh applies to the canonical bot users. Without this, a
freshly hired agent's PATCH to assign itself an issue returned 403 Forbidden
and the dev-agent polled forever logging "claim lost to <none>".
issue_claim() now captures the PATCH HTTP status via `-w '%{http_code}'`
instead of swallowing failures with `curl -sf ... || return 1`. A 403 (or
any non-2xx) now surfaces a distinct log line naming the code — the missing
collaborator root cause would have been diagnosable in seconds instead of
minutes.
Also updates the lib-issue-claim bats mock to handle the new `-w` flag and
adds a regression test covering the HTTP-error log surfacing path.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Forgejo's assignees PATCH is last-write-wins, so two dev agents polling
concurrently could both observe .assignee == null at the pre-check, both
PATCH, and the loser would silently "succeed" and proceed to implement
the same issue — colliding at the PR/branch stage.
Re-read the assignee after the PATCH and bail out if it isn't self.
Label writes are moved AFTER this verification so a losing claim leaves
no stray in-progress label to roll back.
Adds tests/lib-issue-claim.bats covering the three paths:
- happy path (single agent, re-read confirms self)
- lost race (re-read shows another agent — returns 1, no labels added)
- pre-check skip (initial GET already shows another agent)
Prerequisite for the LLAMA_BOTS parametric refactor that will run N
dev containers against the same project.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add issue_is_dev_claimable() helper to lib/issue-lifecycle.sh that checks
whether an issue's labels are compatible with dev-agent ownership. Labels
like bug-report, vision, in-triage, prediction/*, action, and formula
indicate another agent owns the issue.
In dev-poll.sh, replace the vision-only skip with the new helper so that
ALL non-dev labels are excluded from stale detection. This prevents
dev-poll from relabeling bug-reports (or other agent-owned issues) as
blocked while they are being triaged.
Also removes the now-redundant formula/prediction guard block in the
orphan section, since issue_is_dev_claimable covers those labels.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add 60-second grace period to stale in-progress detection in dev-poll.sh.
When a poller sees an in-progress issue with no assignee/PR/lock, it now
checks the timeline API for when the label was added. If <60s ago, it
skips stale detection to allow the claiming agent time to finish its
assign+label sequence.
Also documents the intentional assign-before-label ordering in
issue_claim() that minimizes the race window.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Remove ensure_blocked_label_id() from ci-helpers.sh; _ilc_ensure_label_id()
in issue-lifecycle.sh is the canonical, general implementation. Update the
stale comment that referenced the removed function.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>