Article · Engineering
ai-worker, Part 1: From Issue to Reviewed Merge
The current ai-worker workflow: three bot roles, approved sequential milestones, evidence-based review and repair, CI-gated delivery, and a web control plane.
Read in another language: RUai-worker coordinates planning, implementation, and code review for the repositories behind Amitable. Issues describe the requested outcome, comments record decisions, and pull requests carry the resulting code. A Python controller manages the workflow while model sessions handle source exploration, implementation, and inspection.
This article reflects the implementation as of November 10, 2026, at worker
commit 824c821. Recent changes introduce three bot roles, sequential execution
for new milestone plans, ordered provider selection, and a web control plane.
Part 2 explains the architecture behind those
behaviors, including isolation, scheduling, evidence, and recovery.
Choose the entry point and authority
The current roles are planner-bot, worker-bot, and reviewer-bot, each using
a non-admin Forgejo account. They separate planning and merge coordination,
implementation, and independent inspection. Existing ai-worker service names,
branch prefixes, ownership markers, and command aliases remain compatible.
Assign an open issue to planner-bot when the work needs a plan and milestone
breakdown. Describe observable behavior and constraints: for a record-export
feature, specify who can export, which records are included, and what the output
contains. Ambiguities become planning questions before implementation starts.
An issue authored by a repository writer can instead be assigned directly to
worker-bot. This authorizes implementation from the issue and human requirements
without a separate planning phase or plan approval. The worker reports explicit
acceptance criteria; unclear requirements still block work. A Forgejo branch
reference selects the target context, otherwise the default branch is used.
Standalone PRs can receive reviewer-bot inspection without a linked issue or plan. When no criteria are supplied, the reviewer uses the description, discussion, and source to inspect correctness, security, and regressions rather than inventing requirements. Review approval alone does not grant merge authority.
Polling, permission checks, Git publication, CI inspection, status updates, and eligible merges use ordinary code. An idle task or a task awaiting approval does not need a model session to remain visible.
Approve a specific plan revision
Planning inspects a pinned repository snapshot without changing code or running dependency setup, tests, or builds. The plan records the outcome, acceptance criteria, bounded milestones, supported validation commands, risks, and questions. New plans execute milestones sequentially. A genuinely small issue may need only one milestone.
The planner maintains its existing plan comment when revising requirements and updates a persistent progress report. Each revision also gets a new notification comment identifying the revision and whether approval is awaited. This provides a fresh approval target even though the main plan comment is edited in place.
A human with repository Write, Admin, or Owner permission can approve with a new, unedited comment:
@planner-bot approve-plan p-<revision>
Replace the placeholder with the revision printed beneath the plan. Alternatively,
add a 👍 reaction to the planner’s unedited, revision-specific “awaiting approval”
notification. A reaction on the main plan comment does not count. Bot accounts
cannot provide human approval; legacy @ai-worker commands remain accepted.
Approval applies to that revision and its requirements. Open questions prevent execution, and requirements changes invalidate earlier approval. Writer-supplied reference images can form part of the planning context: adding, changing, or removing an eligible attachment participates in the requirements fingerprint and can trigger replanning.
New milestones execute in order
An approved milestone has an immutable identifier such as m1, a bounded scope,
acceptance criteria, and validation obligations. The controller activates the
first unfinished milestone and records its execution on the parent task. New
sequential plans do not create the dependency-graph child issues used by the
older parallel workflow.
Each milestone produces a PR from a managed branch such as
ai-worker/issue-N-m1 into the issue’s integration branch. The next milestone
starts after the current milestone’s merge is confirmed. Even logically
independent milestones in the same new plan run in sequence.
Consider this illustrative record-export plan: m1 defines the shared
contract, m2 implements permission-checked export, and m3 adds the interface.
The names are an example, not a historical delivery or benchmark.
Across different parents, implementation jobs can use the configured execution slots concurrently. Planning and review can overlap other work; a published PR waiting for review or CI releases implementation capacity. Repairs to an already published, reviewed PR have a limited exception to the same-parent scheduling restriction. Actionable review and CI fixes take priority over new implementation.
The controller keeps default-branch changes synchronized into integration. Conflicts can be resolved by the implementation guest against a pinned default commit; returned work must include that commit before publication. Repair uses ordinary commits and preserves retained work rather than force-pushing it away.
Implementation must return checkable evidence
The implementation session receives the approved active scope, source snapshot, prior findings, and retained work. It follows repository guidance and commits through the repository’s hooks. For Amitable, broad build, schema, and affected unit checks normally run through the pre-commit hook, with full coverage checks in PR CI; focused relevant e2e checks and explicitly approved measurements still run separately. Hooks are not bypassed.
The result accounts for every active criterion and records the actual validation
commands and outcomes. A completion flag cannot override failed checks, missing
evidence, or uncommitted work. Stable check_id values distinguish scenarios and
allow retries without letting a narrow passing run erase a different failed suite.
New validation requirements separate evidence_required from pass_required.
An approved aggregate coverage measurement, for example, may require complete
baseline and head measurements while allowing an intermediate threshold to be
advisory. Assertion failures, environment failures, and missing measurements do
not become acceptable merely because the threshold is advisory.
Receipts bind measurements to exact commits and scopes, with covered and total counts where required. Missing or stale mandatory evidence returns to implementation before publication or merging. Otherwise successful work missing only criterion evidence can be corrected from retained code and actual receipts without requiring an unnecessary new commit.
Failed required checks and eligible reporting gaps enter bounded recovery, normally up to three attempts for the unchanged snapshot. Quota deferrals do not consume that budget. Questions and scope changes retain their human-input or replanning paths.
Review and repair are separate decisions
Reviewer-bot starts a fresh session against the complete pinned diff and surrounding source. Ordinary review does not install dependencies or run tests, lint, typechecks, builds, or e2e. It reports concrete correctness, security, or regression findings and precise source references. Implementation receipts remain the evidence for executed checks.
Findings create an explicit repair obligation. Worker-bot must account for each finding with a committed fix and regression evidence, a source-backed dispute, or an incomplete result explaining the blocker. Existing passing tests alone do not resolve a finding. Incomplete or unchanged “already complete” answers receive corrective feedback within the repair budget.
A dispute goes to fresh independent inspection, even when head and base have not changed. Worker-bot cannot clear its own findings. Eligible incomplete reviews and implementation blockers can also enter bounded recovery instead of remaining stalled forever. Exhaustion reports the unresolved gaps and the explicit retry command; changing scope still requires a human decision.
Complete reviews publish approval or change requests. Draft and WIP PRs are normally skipped, with a specific exception for final review in retained legacy parallel features. Changed snapshots invalidate prior review clearance.
Delivery depends on the recorded workflow
Milestone PRs into integration need accepted implementation evidence, independent review, no blocking change request, and applicable checks and server protections. Plan approval authorizes these intermediate merges without another human approval. Once milestone work integrates, the controller maintains an integration-to-default PR, keeping it WIP while unfinished milestones remain.
For a completed new sequential plan, the final PR becomes ready and can merge automatically after integration is synchronized, the current head satisfies configured CI, mergeability is confirmed, and no change request remains. This path does not require a separate final human approval, final automated review, or the legacy combined-validation job. The milestone receipts were checked before those milestones integrated.
| Workflow | Plan authorization | Final merge gate |
|---|---|---|
| New sequential milestone plan | Human approval of the revision | Current applicable CI, mergeability, no change request, server protections |
| Direct issue targeting default | Writer-authored assignment authorizes implementation | Formal human approval of the current head, accepted review and validation, applicable CI |
| Existing parallel feature | Its recorded approved graph | Independent final review, combined validation, current-head human approval, applicable CI |
Configured CI dispatch is tied to the current head. A head change requires fresh checks; failed final CI can trigger bounded repair on integration and another dispatch. Missing configured workflows leave delivery waiting for CI. Where dispatch is not configured, the controller can accept an absence of CI statuses, but it does not treat pending or failed checks as success or bypass server rules.
Merge requests are non-forced and guarded by the expected head. Delivery is recorded only after the remote merge is confirmed. A merge attempt that makes no progress yields to other runnable tasks. Delivery means integration into the target branch; application deployment follows its own release process.
Observing and controlling work
The web control plane adds Overview, Tasks, Logs, and Settings screens alongside the terminal dashboard. Overview displays the shared scheduler, active slots, phase/provider/model details, recorded quota, host and guest resources, and errors. Tasks expose milestone history and results; Logs provides bounded recent journal output; Settings previews changes to supported configuration.
Settings also shows cached repository access status for each configured role. Check access inspects permissions; Repair access grants missing non-admin Write access and verifies it through the bot logins. Adding repositories through Save performs that provisioning for the newly added entries. Partial failures leave settings saved and display actionable warnings. Merely opening Settings does not check permissions, and removing a repository does not revoke existing access.
Start now requests an immediate check when capacity is available. Pause scheduling leaves active jobs running. Stop selected slot requires confirmation identifying the current job and a server-side recheck before stopping it. Resume is restricted to an appropriately paused, previously enabled and validated scheduler; initial activation and recovery remain operator tasks outside the web UI.
Read-only refreshes do not call providers or Forgejo. Recorded quotas can be stale: the asterisk shown in the screenshot marks an old reading, not new execution authorization. Failed quota observations are not used to admit jobs. Settings changes affect subsequent jobs while running work keeps its recorded configuration.
Revising, stopping, and cleaning up
Put requirements changes on the parent and approve a fresh revision. Existing milestone scopes keep their identifiers; changed scopes need fresh IDs. Retained commits can be explicitly carried into replacement work. Close superseded open PRs before their replacements execute.
Use @planner-bot retry on planning issues, @worker-bot retry on implementation
issues, and @reviewer-bot review or @reviewer-bot retry on PRs. Closing or
unassigning the parent prevents further feature work, publication, and merging;
it does not undo confirmed merges.
After confirmed final delivery, cleanup removes the feature’s local guests, bundles, logs, screenshots, and retired attempts. SQLite retains results, merge evidence, and a cleanup receipt; Forgejo retains published discussion and evidence. Recovery artifacts are preserved while work remains unfinished or ambiguous.
Continue with Part 2: Architecture and Execution Boundaries for the mechanisms behind these decisions.
