A work item filed without a plan has no lane: executor is plan-only, so it silently falls to the global default #489

Merged
toasterson merged 3 commits from claude/wi-019f9946-a-work-item-filed-without-a-plan-has-no into main 2026-08-06 17:44:50 +00:00
Owner

Anima work item 019f9946-08a4-7d90-a24e-a043588747da.

Problem

work_items.executor is only ever populated from the item's plan. create_work_item — gRPC and MCP alike — takes no executor argument, and there is no project-level default either (projects has no executor column). So a work item filed directly against a project, with no plan, is created with a NULL executor and routes to whatever ANIMA_SCHED_DEFAULT_EXECUTOR happens to be set to on the server pod (today: opencode).

That is the normal way bugs, gap analyses and follow-ups get filed. It is how every work item filed during the 2026-07-25 fleet review was created.

Why it matters

A project assigned to a specific akh has no way to say so. Akh-Medu is meant to run on tecton — every WI that came from a plan carries executor='tecton' — but a WI filed straight against the project carries nothing and is dispatched to the opencode container lane instead. For an akh that edits files on its own filesystem, that is not a slower path, it is the wrong one.

Caught live 2026-07-25: akh-medu WI 019f9943-170b-78e0-95d8-6c9b4565d48a was filed plan-less, came out with executor NULL against 47 sibling WIs all set to tecton, and had to be corrected by hand before it would route.

Open work items with no executor, by project:

OpenIndiana  draft   120
illumos      draft    91
Anima        draft    17
Anima        parked   11
Akh-Medu     draft    10
Anima        draft     8   (has a plan, still unset)
Anima        ready     7   ← in the dispatch queue right now
sia          parked    7

The seven Anima items in ready are dispatchable today and will all land on the default lane regardless of what suits them — a server-side Rust change and a PWA tweak get the same executor by accident rather than by choice.

Proposed fix

  1. Add an executor argument to CreateWorkItem (gRPC + MCP), so a caller who knows the lane can say so.
  2. Give projects a default_executor, and resolve in the order: explicit argument → the item's plan → the project's default → ANIMA_SCHED_DEFAULT_EXECUTOR. This is the same shape ADR 0024 already uses for workflow resolution, and it is what makes "Akh-Medu runs on tecton" a fact the system holds rather than a convention people remember.
  3. Set Akh-Medu.default_executor = tecton and backfill its 10 unset drafts.
  4. Surface the resolved executor on the WI row in the PWA. Today the only way to know which lane will pick an item up is to query the column.

Acceptance criteria

  • A WI created with an explicit executor keeps it.
  • A plan-less WI in a project with a default executor inherits the project's, not the global one.
  • An akh-medu WI filed with no plan and no argument dispatches to tecton.
  • The resolution order is covered by tests at each fallback step.
  • No open WI in a project with a default executor is left NULL.
  • 019f990a-3948-7a73-9a6a-f57287250435 — akh-medu WIs parking; a WI sent to the wrong lane is one more way to burn the retry budget.
  • Akh-Medu 019f9943-170b-78e0-95d8-6c9b4565d48a — the item that surfaced this.
  • Same class as the MCP phase default fixed in PR #362: a create path leaving a routing column NULL, and nothing noticing until the work fails to move.
Anima work item `019f9946-08a4-7d90-a24e-a043588747da`. ## Problem `work_items.executor` is only ever populated from the item's **plan**. `create_work_item` — gRPC and MCP alike — takes no executor argument, and there is no project-level default either (`projects` has no executor column). So a work item filed directly against a project, with no plan, is created with a NULL executor and routes to whatever `ANIMA_SCHED_DEFAULT_EXECUTOR` happens to be set to on the server pod (today: `opencode`). That is the normal way bugs, gap analyses and follow-ups get filed. It is how every work item filed during the 2026-07-25 fleet review was created. ## Why it matters A project assigned to a specific akh has no way to say so. Akh-Medu is meant to run on **tecton** — every WI that came from a plan carries `executor='tecton'` — but a WI filed straight against the project carries nothing and is dispatched to the opencode container lane instead. For an akh that edits files on its own filesystem, that is not a slower path, it is the wrong one. Caught live 2026-07-25: akh-medu WI `019f9943-170b-78e0-95d8-6c9b4565d48a` was filed plan-less, came out with `executor` NULL against 47 sibling WIs all set to `tecton`, and had to be corrected by hand before it would route. Open work items with no executor, by project: ``` OpenIndiana draft 120 illumos draft 91 Anima draft 17 Anima parked 11 Akh-Medu draft 10 Anima draft 8 (has a plan, still unset) Anima ready 7 ← in the dispatch queue right now sia parked 7 ``` The seven Anima items in `ready` are dispatchable today and will all land on the default lane regardless of what suits them — a server-side Rust change and a PWA tweak get the same executor by accident rather than by choice. ## Proposed fix 1. Add an executor argument to `CreateWorkItem` (gRPC + MCP), so a caller who knows the lane can say so. 2. Give `projects` a `default_executor`, and resolve in the order: explicit argument → the item's plan → the project's default → `ANIMA_SCHED_DEFAULT_EXECUTOR`. This is the same shape ADR 0024 already uses for workflow resolution, and it is what makes "Akh-Medu runs on tecton" a fact the system holds rather than a convention people remember. 3. Set `Akh-Medu.default_executor = tecton` and backfill its 10 unset drafts. 4. Surface the resolved executor on the WI row in the PWA. Today the only way to know which lane will pick an item up is to query the column. ## Acceptance criteria - A WI created with an explicit executor keeps it. - A plan-less WI in a project with a default executor inherits the project's, not the global one. - An akh-medu WI filed with no plan and no argument dispatches to tecton. - The resolution order is covered by tests at each fallback step. - No open WI in a project with a default executor is left NULL. ## Related - `019f990a-3948-7a73-9a6a-f57287250435` — akh-medu WIs parking; a WI sent to the wrong lane is one more way to burn the retry budget. - Akh-Medu `019f9943-170b-78e0-95d8-6c9b4565d48a` — the item that surfaced this. - Same class as the MCP phase default fixed in PR #362: a create path leaving a routing column NULL, and nothing noticing until the work fails to move.
toasterson force-pushed claude/wi-019f9946-a-work-item-filed-without-a-plan-has-no from 59468beb33 to b0d74dce1d 2026-08-03 17:07:09 +00:00 Compare
toasterson changed title from WIP: A work item filed without a plan has no lane: executor is plan-only, so it silently falls to the global default to A work item filed without a plan has no lane: executor is plan-only, so it silently falls to the global default 2026-08-04 01:16:06 +00:00
toasterson force-pushed claude/wi-019f9946-a-work-item-filed-without-a-plan-has-no from d796d2ea3e to 518464ee2d 2026-08-04 21:51:15 +00:00 Compare
toasterson force-pushed claude/wi-019f9946-a-work-item-filed-without-a-plan-has-no from 518464ee2d to d42e69c1f9 2026-08-04 22:34:48 +00:00 Compare
toasterson force-pushed claude/wi-019f9946-a-work-item-filed-without-a-plan-has-no from d42e69c1f9 to 6dc4a873ab 2026-08-05 20:23:01 +00:00 Compare
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
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
toasterson/Anima!489
No description provided.