| status | implemented |
|---|
Operations Center has six board-facing worker lanes:
goaltestimproveproposereviewspec
The lanes are not independent scripts. They are stages in a board-level workflow.
goal -> In Review (PR opened, review watcher takes over)
goal -> test -> done
goal -> blocked -> improve -> follow-up goal/test or human attention
test -> goal when verification fails
propose -> bounded goal/test/improve tasks when the board is quiet or recent signals justify it
review -> Done (self-review LGTM or human 👍 → PR merged)
review -> human review phase (self-review unable to resolve → escalated to human)
spec -> campaign of goal/test_campaign/improve_campaign tasks when trigger fires
spec -> recovery/revision when campaign stalls; abandon when budget exhausted
- Consumes
task-kind: goaltasks inReady for AI. - Runs implementation work in an isolated workspace.
- Ends with one explicit next-step outcome:
- success with no explicit verification need ->
Review - success with explicit verification need -> creates
task-kind: test - blocked/failure -> leaves the task
Blockedfor improve triage
- success with no explicit verification need ->
- Consumes
task-kind: testtasks inReady for AI. - Runs verification work.
- Ends with one explicit next-step outcome:
- verification success ->
Done - verification failure -> creates
task-kind: goal
- verification success ->
- Consumes explicit
task-kind: improvetasks. - Regularly inspects
Blockedtasks. - Interprets failures, creates bounded follow-up work, or routes the task to human attention.
Blocked-task handling lives inside improve, not in a separate unblocker lane.
- Monitors board/system state when normal implementation and verification lanes are quiet.
- Uses bounded signals such as idle board state, repeated blocked patterns, and recent retained findings.
- Creates bounded Plane tasks instead of directly editing the repo.
- Places strong, high-confidence tasks in
Ready for AIand lower-confidence tasks inBacklog.
- Monitors board state and external triggers (drop-file, Plane label, queue drain) to decide when to start a spec-driven campaign.
- Autonomously brainstorms what is worth building via direct Anthropic API call, producing a spec doc written to
docs/specs/. - Converts the spec into a bounded campaign of Plane tasks (
goal,test_campaign,improve_campaign) covering implement → test → improve phases. - Tracks campaign progress in
state/campaigns/active.json(viaCampaignStateManager). - Runs recovery logic each cycle: revises the spec (up to 3 times) when the campaign stalls; abandons and self-cancels when the 72-hour budget is exhausted.
- Suppresses heuristic
proposecandidates that overlap an active campaign'sarea_keywords, preventing conflicting parallel board work. - Picks up operator direction from a drop-file (
state/spec_director_trigger.md) or a Plane task label (spec-director: trigger).
- Manages open PRs created by the
goallane whenawait_review: trueis set for the repo. - Operates as a two-phase state machine per PR, tracked in
state/pr_reviews/<task_id>.json:- Stage 1 — self-review: kodo reads the diff against the base branch and writes a verdict file (
LGTMorCONCERNS). LGTM triggers merge. CONCERNS triggers a kodo revision pass followed by another self-review cycle (up toreviewer.max_self_review_loopstimes). - Stage 2 — human review: if self-review cannot resolve its concerns, the watcher posts an escalation comment and waits for human input. Human 👍 on the PR or bot reply triggers merge. Human comment triggers a kodo revision pass; bot replies when done (max 3 loops). Timeout of 1 day triggers auto-merge.
- Stage 1 — self-review: kodo reads the diff against the base branch and writes a verdict file (
- All bot-posted comments carry a
<!-- operations-center:bot -->marker. The watcher never re-processes its own comments. reviewer.bot_loginsin config lists accounts whose comments are always ignored.reviewer.allowed_reviewer_loginsoptionally restricts human-phase revision triggers to a whitelist.- On startup, the watcher backfills state files for any open PRs that pre-date it.
goalmay createtestfollow-up tasks.goalmay open a PR and hand off toreviewwhenawait_review: true.testmay creategoalfollow-up tasks.improvemay create boundedgoal,test, or explicitimprovefollow-up tasks.proposemay create boundedgoal,test, orimprovetasks when its guardrails allow it.reviewmarks tasks Done on merge; does not create follow-up tasks.speccreates a campaign ofgoal,test_campaign, andimprove_campaigntasks when a trigger fires. It does not directly implement changes.- Every handoff should remain visible on the board through comments and child-task context.
Follow-up tasks include:
original_task_idoriginal_task_titlesource_worker_rolesource_task_kindfollow_up_task_kindhandoff_reason
The parent task receives a comment with created child task ids, and the child task receives an initial source comment.
BacklogReady for AIRunningReview— task completed, changes pushed; no PR automationIn Review— PR opened; review watcher is driving mergeBlockedDone
These are board-facing workflow states, not a queue implementation.
The spec lane introduces two new task kinds for the test and improve phases of a campaign:
test_campaign— picked up by thetestrole worker (alongside plaintest); runskodo --testfor adversarial testing of campaign implementation.improve_campaign— picked up by theimproverole worker (alongside plainimprove); runskodo --improvefor simplification/architecture/usability passes.
Campaign implement phase tasks use the standard goal task kind and are executed by the existing goal lane workers unchanged.
The ROLE_TASK_KINDS map in worker/main.py controls which task kinds each role claims:
ROLE_TASK_KINDS = {
"goal": {"goal"},
"test": {"test", "test_campaign"},
"improve": {"improve", "improve_campaign"},
"fix_pr": {"fix_pr"},
}When Kodo embeds <!-- cp:question: ... --> in its output, the task enters a human-in-the-loop sub-flow inside the Blocked state:
goal [Running] -> Blocked (awaiting_input)
↓
improve extracts question, posts Plane comment
↓ (every 8 cycles)
human replies on Plane task
↓
improve injects answer, re-queues -> Ready for AI
This flow is distinct from validation_failure or infra_tooling blocks — it is not retried automatically. It waits for a human answer. Once detected and re-queued, the task re-enters the normal goal execution cycle with the answer injected into its description.
This lifecycle contract does not imply:
- webhooks
- distributed scheduling
- queue infrastructure
- unlimited retries
- automatic requeue storms
The current implementation is a local polling workflow with explicit next-step semantics.