| status | implemented |
|---|
Build a self-hosted AI execution wrapper that uses Plane as the Jira-like board and Kodo as the coding engine, with explicit repo and base-branch selection per task.
- Worker fetches one Plane work-item by id.
- Parser extracts
Executionmetadata,Goal, and optionalConstraints. - Worker validates mode support (
goal,test_campaign,improve_campaignmodes). - Worker resolves repo config and base-branch policy.
- Worker creates isolated ephemeral clone and task branch.
- If the branch already exists on remote (retry), it is checked out with tracking and the base branch is merged in. Conflict markers are left in the working tree for kodo to resolve.
- Worker bootstraps a repo-local Python virtualenv inside the cloned repo when enabled.
- Worker runs baseline validation before kodo; pre-existing failures are flagged separately.
- Worker writes
goal.mdfrom Goal/Constraints (with conflict-resolution preamble if needed). - Worker runs kodo (
--goal-file,--test, or--improvedepending on task kind) and validation commands. - Worker enforces
allowed_pathspolicy for changed files. - Worker commits/pushes only when policy allows.
- When
await_review: true: worker creates a PR and writes a state file for thereviewwatcher to manage. Task transitions toIn Review. - Worker writes retained artifacts under
tools/report/kodo_plane/<timestamp>_<task_id>_<run_id>/. - Worker posts a short Plane comment and updates status.
- webhook ingestion
- concurrency locks
- multi-repo orchestration
- distributed scheduling
The spec watcher creates campaign tasks with two additional task kinds:
test_campaign— runskodo --testfor adversarial testing; claimed by thetestrole worker.improve_campaign— runskodo --improvefor simplification/architecture passes; claimed by theimproverole worker.
Campaign implement tasks use the standard goal task kind. The spec_campaign_id field in the ## Execution block links each task back to its originating spec.
## Execution
repo: MyRepo
base_branch: main
mode: goal
allowed_paths:
- src/
- tests/
## Goal
Improve reporting output and ensure policy violations are visible.
## Constraints
- Keep changes inside wrapper service code.
- Current operation is manual-by-task-id (no scheduler/webhook yet).
- If validation fails but
push_on_validation_failureis enabled, the branch may still be pushed as draft output. This does not indicate run success. - Changed-file policy evaluation includes tracked modifications, additions, deletions, renames, and untracked files before commit.
- Python validation is intended to run inside a repo-local virtualenv in the cloned workspace, not against host-global Python packages.
- Default bootstrap path is
.venvat the cloned repo root. - Default bootstrap commands are
python3 -m venv .venv, pip upgrade, and.venv/bin/pip install -e .[dev]. - Repos can override
python_binary,venv_dir,install_dev_command, or disable bootstrap withbootstrap_enabled: false.
PlaneClient._request retries transient failures automatically before raising:
- Connection errors (
ConnectError,TimeoutException,RemoteProtocolError): up to 4 attempts with linear backoff (2s, 4s, 6s between retries) - 5xx responses (502, 503, 504): same retry logic
- 429 rate-limit responses: existing retry logic (unchanged)
On the 4th attempt, errors are re-raised. This prevents transient Plane API blips from failing an otherwise successful execution.
The Kodo adapter uses subprocess.Popen with start_new_session=True. This places Kodo in its own process group, isolated from the worker process's session. All cleanup paths use os.killpg to kill the entire group (Kodo + any spawned subprocesses such as Claude worker processes):
os.killpg(os.getpgid(proc.pid), signal.SIGKILL)Timeout path: when the configured kodo.timeout_seconds expires, the process group is killed with SIGKILL. The run result carries exit_code=-1 and a [timeout: process group killed after Ns] note appended to stderr.
SIGTERM path: because Kodo runs in a separate session, a SIGTERM sent to the worker Python process (supervisor stop, OOM killer) does not propagate to the Kodo group automatically. The adapter installs a SIGTERM handler for the duration of each run:
- SIGTERM arrives at the worker process.
- The handler calls
os.killpgon the Kodo process group. - The previous SIGTERM handler is restored and the signal is re-raised so normal Python shutdown (finally blocks, atexit hooks) can still run.
This prevents Kodo subprocesses from becoming orphans that continue consuming CPU and API quota after a worker restart or system shutdown.
- Use
python -m operations_center.entrypoints.smoke.plane --config ... --task-id ... --comment-onlyto verify Plane connectivity and parsing without invoking Kodo. - Smoke runs retain the raw fetched work-item payload in
plane_work_item.json. - Live Plane API behavior still needs to be confirmed by the operator against the target deployment and recorded from retained smoke artifacts.