--- kind: task slug: worker-minimal-tool-loop title: apps/worker — minimal tool loop and worktree-per-brief plan_slug: automation-foundation epic_slug: apps-worker-v1 status: done priority: P1 tenant_id: global owner: unassigned cursor_todo_id: null updated_at: "2026-08-12" agent_prompt: |- Epic: apps/worker v1. Read docs/worker.md and docs/adr-model-routing.md. Consume orchestrator jobs from Redis; resolve model via workspace registry. claim_task / complete_task parity with MCP. Run pnpm lint && pnpm type-check && pnpm test before done. --- # Task summary Ship the baseline `apps/worker` consumer: dequeue `role_dispatch` jobs, run `WorkerSession` tool loop against a git worktree, and close with model + token metadata on `complete_task`. ## Description Core v1 scope from [Epic-apps-worker-v1](./Epic-apps-worker-v1.md). Builds on existing package skeleton (`handle-job.ts`, `minimal-session.ts`, allowlisted tools, worktree helpers). ### Worker loop - `BLPOP` on `echodo:orchestrator:jobs` (same key as orchestrator). - Load brief path + role from job payload; resolve model via shared resolver. - `claim_task` on matching backlog item; run `read_file` / `write_file` / `grep` / `run_command` (allowlist: `pnpm lint`, `pnpm type-check`, `pnpm test`, `git status`, `git diff`). - `complete_task` with `modelAlias`, token totals, outcome. ### Git - One worktree per brief under `WORKER_WORKTREE_BASE`. - Branch naming convention documented for Epic 8 PR linking. ### PR output - Open draft PR via forge adapter from connected repo (Epic 3). ## Subtasks - [ ] Wire live dequeue loop (non-dry-run) end-to-end - [ ] Role prompt = `.cursor/agents/role-*.md` + brief markdown path - [ ] Worktree create/teardown on success and failure - [ ] Draft PR via forge adapter when implementer completes - [ ] `docs/worker.md` matches shipped behavior ## Estimation L ## Acceptance criteria - [ ] One implementer brief from `.convoys/` completes unattended on a connected repo - [ ] `complete_task` includes model alias + token totals - [ ] Failed runs tear down worktree and mark run `failed` - [ ] `WORKER_DRY_RUN=1` still exits cleanly without Redis ## Links - Epic: `./Epic-apps-worker-v1.md` - Plan: `../Plan-automation-foundation.md` - Design reference: Autensa convoy build phase (concepts only — no OpenClaw dependency)