Forgejo: start implementer sessions from a configured intake label #131

Merged
lucas merged 1 commit from agent/issue-130-label-implementer into main 2026-10-28 12:22:06 +01:00
Collaborator

Closes: #130

What changed

  • Config: .omp/forgejo.yaml gets a new implementation section with intake_label, progress_label and max_concurrent (default 1). The parser validates every key and rejects these collisions:

    • the intake label equals issue_handler.label;
    • the progress label equals the intake label.

    labelTriggerFor now also returns "implementation".

  • Label path: an issue_label event gates as the new reason implementer-intake under the same checks as the issue handler: the latest change must have added the label, the sender needs write access, and exactly one workspace must match. runIntake then claims the row and creates the session in the issue clone with base null. It sets the labels and awaits the first turn, then finishes the row:

    • done with reason implementer-intake on success;
    • failed on error;
    • dropped plus a "can't start an implementer" notice when refused.
  • Concurrency: max_concurrent limits how many label-started first turns run at once in each repo. A row over the limit makes the gate return "deferred" and stays pending. While a row is deferred, its artifact key is not pumped, so the queue for that issue keeps its order. Each slot release re-gates the deferred rows. The button does not count toward the limit and is never deferred.

  • Shared core: both paths use the same checkImplementable, launchImplementer and markInProgress code.

    • A usable forgejo_conversation session is archived and replaced, and the issue's mapping moves to the new session.
    • Any other usable session is refused (409, or a notice on the label path).
    • Status/Blocked is still refused.
  • Manual path: no longer requires Agent/Ready. It reads the repo config and removes the intake label and adds the progress label when they are configured. Without that config it changes no labels. A config file it can't read or parse refuses the start with 502 or 422.

.omp/commands/implement.md is unchanged, as the issue requires.

Verification

  • bun test apps/server/src/forgejo passes (365 tests).
  • tsc --noEmit -p apps/server is clean.
  • New tests cover config parsing, each label-path outcome, replacing a conversation session on both paths, and max_concurrent deferring label starts while button starts still go through.
Closes: #130 ## What changed - **Config:** `.omp/forgejo.yaml` gets a new `implementation` section with `intake_label`, `progress_label` and `max_concurrent` (default 1). The parser validates every key and rejects these collisions: - the intake label equals `issue_handler.label`; - the progress label equals the intake label. `labelTriggerFor` now also returns `"implementation"`. - **Label path:** an `issue_label` event gates as the new reason `implementer-intake` under the same checks as the issue handler: the latest change must have added the label, the sender needs write access, and exactly one workspace must match. `runIntake` then claims the row and creates the session in the issue clone with base `null`. It sets the labels and awaits the first turn, then finishes the row: - `done` with reason `implementer-intake` on success; - `failed` on error; - `dropped` plus a "can't start an implementer" notice when refused. - **Concurrency:** `max_concurrent` limits how many label-started first turns run at once in each repo. A row over the limit makes the gate return `"deferred"` and stays `pending`. While a row is deferred, its artifact key is not pumped, so the queue for that issue keeps its order. Each slot release re-gates the deferred rows. The button does not count toward the limit and is never deferred. - **Shared core:** both paths use the same `checkImplementable`, `launchImplementer` and `markInProgress` code. - A usable `forgejo_conversation` session is archived and replaced, and the issue's mapping moves to the new session. - Any other usable session is refused (409, or a notice on the label path). - `Status/Blocked` is still refused. - **Manual path:** no longer requires `Agent/Ready`. It reads the repo config and removes the intake label and adds the progress label when they are configured. Without that config it changes no labels. A config file it can't read or parse refuses the start with 502 or 422. `.omp/commands/implement.md` is unchanged, as the issue requires. ## Verification - `bun test apps/server/src/forgejo` passes (365 tests). - `tsc --noEmit -p apps/server` is clean. - New tests cover config parsing, each label-path outcome, replacing a conversation session on both paths, and `max_concurrent` deferring label starts while button starts still go through.
Add an `implementation` section to .omp/forgejo.yaml (intake_label,
progress_label, max_concurrent). Adding the intake label to an issue now
starts the same implementer session as the deck's button; label-started
first turns are limited per repo by max_concurrent, with excess rows kept
pending until a slot frees.

The manual start no longer requires Agent/Ready and applies the configured
label changes instead of hard-coded ones. Both paths archive and replace a
usable conversation session on the issue and refuse other usable sessions.

Co-Authored-By: Claude Opus 5.5 via omp-deck
lucas approved these changes 2026-10-28 12:22:01 +01:00
lucas merged commit 198ffc0b06 into main 2026-10-28 12:22:06 +01:00
lucas deleted branch agent/issue-130-label-implementer 2026-10-28 12:22:06 +01:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
lucas/omp-deck!131
No description provided.