From 47bb5403b1ed3d22eb62aba557aea48c9d78d366 Mon Sep 17 00:00:00 2001 From: Renn F Date: Sun, 28 Jun 2026 22:59:07 +0200 Subject: [PATCH] [R115] originate ci_watch/dep_update fix tasks as PLANNING coordination roots MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Main-PM-code-impossibility guard (commit e202ce39, Thread 4 of this audit) made team=MAIN_PM + task_type=CODE impossible — a Main PM coordinates, it does not write code. But the ci_watch and dep_update engines still originated their fix tasks as task_type=TaskType.CODE assigned to main-pm, so task_svc.create raised MAIN_PM_NO_CODE and NO fix task was ever opened — a regression introduced by the earlier audit fix (confirmed: the engine tests pass at e202ce39~1 and fail at HEAD). Mirror the hardened self_heal_engine precedent (self_heal_engine.py:197) which already uses task_type=TaskType.PLANNING for its Main-PM coordination root with an explicit 'decompose the fix and delegate the code work to a cell dev — the Main PM does not write the fix itself' description. Both engines now originate PLANNING coordination roots with matching delegation guidance in the description + acceptance criteria. confirmed_by_human stays True for both (they ride the normal delivery flow without the CEO gate, unlike self-heal — intentional per the architecture). The dedupe/open-cap queries (list_open_ci_watch_tasks / list_open_dep_update_tasks) key on source + non-terminal status + git_url, NOT task_type, so the type change does not break dedup (still one open fix task per repo). The two source-test fixtures (test_ci_watch_source / test_dep_update_source) created CODE+MAIN_PM tasks directly to exercise the listing queries — same guard violation; switched to PLANNING (the queries assert on source/status, not task_type, so the fixture type matches the engines' corrected type). --- roboco/services/ci_watch_engine.py | 20 ++++++++++--------- roboco/services/dep_update_engine.py | 14 ++++++++----- .../services/test_ci_watch_source.py | 2 +- .../services/test_dep_update_source.py | 2 +- 4 files changed, 22 insertions(+), 16 deletions(-) diff --git a/roboco/services/ci_watch_engine.py b/roboco/services/ci_watch_engine.py index 89a9d3cc..b1747f2f 100644 --- a/roboco/services/ci_watch_engine.py +++ b/roboco/services/ci_watch_engine.py @@ -155,21 +155,23 @@ class CiWatchEngine(BaseService): f"This project's CI is red on its default branch.\n\n" f"{sample.detail}\n\n" f"Evidence: {sample.raw_ref}\n\n" - "Investigate and fix the regression at its root so CI returns " - "to green. This task was opened automatically by the CI-watch " - "loop and is READY TO START NOW — no approval needed; pick it " - "up and coordinate the fix. It still ships through the normal " - "gates (QA, PR review, and the CEO's merge)." + "This is a Main-PM coordination root: decompose the fix and " + "delegate the code work to a cell dev — the Main PM does not " + "write the fix itself. This task was opened automatically by " + "the CI-watch loop and is READY TO START NOW — no approval " + "needed; plan the fix and delegate it. It still ships through " + "the normal gates (QA, PR review, and the CEO's merge)." ), acceptance_criteria=[ - f"CI on {slug}'s default branch is green again", - "The cause of the failing run is fixed at its root, not " - "masked or skipped", + "The CI regression is decomposed into a code-fix subtask " + "delegated to a cell developer", + f"CI on {slug}'s default branch is green again and the fix " + "merged through the normal gates", ], team=Team.MAIN_PM, assigned_to=_foundation.AGENTS["main-pm"].uuid, created_by=_foundation.AGENTS["system"].uuid, - task_type=TaskType.CODE, + task_type=TaskType.PLANNING, nature=TaskNature.TECHNICAL, estimated_complexity=Complexity.MEDIUM, project_id=cast("UUID", project.id), diff --git a/roboco/services/dep_update_engine.py b/roboco/services/dep_update_engine.py index 008ebfa6..d684aa56 100644 --- a/roboco/services/dep_update_engine.py +++ b/roboco/services/dep_update_engine.py @@ -100,7 +100,9 @@ class DepUpdateEngine(BaseService): title=f"Update dependencies on {slug}", description=( "Dependency updates are available for this project.\n\n" - "Upgrade the dependencies to their latest compatible versions, " + "This is a Main-PM coordination root: decompose the upgrade " + "and delegate the code work to a cell dev — the Main PM does " + "not run the upgrade itself. Plan the dependency upgrade, " "refresh the lockfile(s), and make sure the full gate passes " "with no behavioural breakage. This task was opened " "automatically by the dependency-update bot and is READY TO " @@ -108,14 +110,16 @@ class DepUpdateEngine(BaseService): "normal gates (QA, PR review, and the CEO's merge)." ), acceptance_criteria=[ - "Dependencies are upgraded to latest compatible and the " - "lockfile(s) are refreshed", - "The full quality gate passes with no behavioural regression", + "The dependency upgrade is decomposed into a code-fix " + "subtask delegated to a cell developer", + "Dependencies are upgraded to latest compatible, the " + "lockfile(s) are refreshed, and the full quality gate passes " + "with no behavioural regression", ], team=Team.MAIN_PM, assigned_to=_foundation.AGENTS["main-pm"].uuid, created_by=_foundation.AGENTS["system"].uuid, - task_type=TaskType.CODE, + task_type=TaskType.PLANNING, nature=TaskNature.TECHNICAL, estimated_complexity=Complexity.MEDIUM, project_id=cast("UUID", project.id), diff --git a/tests/integration/services/test_ci_watch_source.py b/tests/integration/services/test_ci_watch_source.py index fd7aa639..3669e51e 100644 --- a/tests/integration/services/test_ci_watch_source.py +++ b/tests/integration/services/test_ci_watch_source.py @@ -86,7 +86,7 @@ async def _make_ci_watch_task( team=Team.MAIN_PM, assigned_to=MAIN_PM_UUID, created_by=SYSTEM_UUID, - task_type=TaskType.CODE, + task_type=TaskType.PLANNING, nature=TaskNature.TECHNICAL, estimated_complexity=Complexity.MEDIUM, project_id=cast("UUID", project.id), diff --git a/tests/integration/services/test_dep_update_source.py b/tests/integration/services/test_dep_update_source.py index f3e91c7e..454e8a4f 100644 --- a/tests/integration/services/test_dep_update_source.py +++ b/tests/integration/services/test_dep_update_source.py @@ -84,7 +84,7 @@ async def _make_task( team=Team.MAIN_PM, assigned_to=MAIN_PM_UUID, created_by=SYSTEM_UUID, - task_type=TaskType.CODE, + task_type=TaskType.PLANNING, nature=TaskNature.TECHNICAL, estimated_complexity=Complexity.MEDIUM, project_id=cast("UUID", project.id),