Skip to content

Reconcile the volunteer-claim contract: claim prompt says do NOT add in-progress, issue-watcher now does #6112

Description

@atomantic

Problem

Two code paths handle the same event — a human comments on an unassigned issue asking to work on it — and they now disagree on what forge state to write.

server/services/taskPromptDefaults/prompts.js (claim-issue agent, Phase 1 handoff) instructs verbatim:

remove $ME as an assignee if it was present and differs from the claimant, leave contributor-invitation labels intact, do NOT create a worktree, do NOT add in-progress

server/services/issueWatcher.js#assignVolunteer (deterministic gather pass, shipped in PR #6111) now sets the assignee and stamps in-progress, and does not release good first issue / help wanted.

Which one ran decides the resulting forge state. That is exactly the drift the shared IN_PROGRESS_LABEL constant was moved to lib/dispatchLabels.js to prevent, one level up: the spelling is shared, the policy is not.

Consequences currently shipped

  1. STALLED on every reconcile pass. issueReconcile.js#classifyIssue returns STALLED for an issue that is open + in-progress with no merged PR and no live claim. A volunteer who has been assigned but has not opened a PR matches exactly, on every pass, indefinitely if they abandon it. Today this is log-only (cosTaskPreStepBlocks.js emits one info line; it does not dispatch an agent or block the park), so it is noise rather than spend — but it is an applier with no releaser, and every other flow that stamps in-progress owns its release (claim Phase 6/7, the zombie heal).
  2. Stale contributor invitations. formatContributorLabelReleaseCommands exists because "this issue is taken now, so it must stop advertising itself to a human." The watcher marks it taken and leaves both invitations up.

Decision to make

Pick one policy and make both paths implement it. The two coherent options:

  • (A) A volunteer claim is a claim. Both paths set the assignee, stamp in-progress, and release the contributor labels. Requires: editing the claim prompt (PROMPT_VERSIONS bump + prior default preserved in PREVIOUS_DEFAULT_PROMPTS + a scripts/migrations/ entry), adding a contributor-label release to assignVolunteer, and extending the reconcile release path to cover "in-progress + non-owner assignee + no PR + stale N days" so the marker has a releaser.
  • (B) A volunteer claim is only an assignee. Revert the in-progress stamp from assignVolunteer and leave the prompt as-is. Cheapest, and perpetualWork.js#isActionableIssue already excludes any issue held by a non-self assignee — so queue exclusion does not depend on the label. Costs the Issues-tab hide the user asked for.

Recommendation: (A). The user's own manual practice on issue #6072 was assign + in-progress, and the repo's label description is literally "Claimed and being worked" — not "autonomously claimed". (B) is a revert of a deliberate request.

Encode the resulting policy once — a volunteerClaimLabels() helper in lib/dispatchLabels.js beside formatContributorLabelReleaseCommands — and render the prompt's handoff step from it, the way CONTRIBUTOR_RELEASE_GH is already interpolated. Note formatContributorLabelReleaseCommands emits shell text; the programmatically reusable piece is the already-exported CONTRIBUTOR_LABELS.

Related

markIssueInProgress's lazy label-create is the third bespoke one in the tree (layeredIntelligence/forgeFiler.js#ensureForgeLabels, autonomousJobs/selfDiagnostics.js#ensureDiagnosticsLabels). forgeFiler.js#applyBlockingLabel is the same "add one label to an existing issue" shape with no lazy create, so it carries the same latent 422. A shared applyForgeLabel({ exec, repoSpec, number, label }) driven by dispatchLabelSpec would be ~10 lines and cover all four — worth folding in if (A) is chosen, since (A) touches this code anyway.

Context: PR #6111, issue #6072.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

area:cos-agentsChief-of-Staff autonomous agentseffort:mediumEffort: mediummodel:mediumModel size: mediumplanTracked by /do:replanplanner:opus-5Plan authored by the opus-5 model

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions